1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-06-17 07:40:47 +03:00
inform7/inter/bytecode-module/Chapter 3/Inter Data Types.w

524 lines
19 KiB
OpenEdge ABL
Raw Normal View History

2019-02-05 02:44:07 +02:00
[Inter::Types::] Inter Data Types.
A primitive notion of data type, below the level of kinds.
2022-01-28 01:38:14 +02:00
@
@d inter_ti unsigned int
@d signed_inter_ti int
=
2019-02-05 02:44:07 +02:00
typedef struct inter_data_type {
2020-07-01 02:58:55 +03:00
inter_ti type_ID;
2019-02-05 02:44:07 +02:00
struct text_stream *reserved_word;
long long int min_value;
long long int max_value;
int enumerated;
2020-05-09 15:07:39 +03:00
CLASS_DEFINITION
2019-02-05 02:44:07 +02:00
} inter_data_type;
inter_data_type *int32_idt = NULL;
inter_data_type *unchecked_idt = NULL;
@ =
dictionary *idt_lookup = NULL;
2020-07-01 02:58:55 +03:00
inter_data_type *Inter::Types::create(inter_ti ID, text_stream *name, int A, int B, int en) {
2019-02-05 02:44:07 +02:00
inter_data_type *IDT = CREATE(inter_data_type);
IDT->type_ID = ID;
IDT->reserved_word = Str::duplicate(name);
IDT->min_value = A;
IDT->max_value = B;
IDT->enumerated = en;
if (idt_lookup == NULL) idt_lookup = Dictionaries::new(128, FALSE);
Dictionaries::create(idt_lookup, name);
Dictionaries::write_value(idt_lookup, name, (void *) IDT);
return IDT;
}
int Inter::Types::is_enumerated(inter_data_type *idt) {
if ((idt) && (idt->enumerated)) return TRUE;
return FALSE;
}
2020-07-01 02:58:55 +03:00
inter_data_type *Inter::Types::find_by_ID(inter_ti ID) {
2019-02-05 02:44:07 +02:00
inter_data_type *IDT;
LOOP_OVER(IDT, inter_data_type)
if (ID == IDT->type_ID)
return IDT;
return NULL;
}
inter_data_type *Inter::Types::find_by_name(text_stream *name) {
dict_entry *de = Dictionaries::find(idt_lookup, name);
if (de) return (inter_data_type *) Dictionaries::read_value(idt_lookup, name);
return NULL;
}
2020-07-01 02:58:55 +03:00
inter_ti Inter::Types::transpose_value(inter_ti V1, inter_ti V2, inter_ti *grid, inter_ti grid_extent, inter_error_message **E) {
switch (V1) {
case DWORD_IVAL:
case PDWORD_IVAL:
case LITERAL_TEXT_IVAL:
case REAL_IVAL:
case GLOB_IVAL:
case DIVIDER_IVAL:
V2 = grid[V2];
break;
}
return V2;
}
inter_error_message *Inter::Types::validate(inter_package *owner, inter_tree_node *P, int index, inter_symbol *kind_symbol) {
inter_symbols_table *T = InterPackage::scope(owner);
if (T == NULL) T = Inode::globals(P);
inter_ti V1 = P->W.instruction[index];
inter_ti V2 = P->W.instruction[index+1];
return Inter::Types::verify_inner(P, kind_symbol, V1, V2, T);
}
inter_error_message *Inter::Types::validate_local(inter_tree_node *P, int index, int kind_index, inter_symbols_table *T) {
inter_symbol *kind_symbol = NULL;
if (P->W.instruction[kind_index])
kind_symbol = InterSymbolsTable::symbol_from_ID(T, P->W.instruction[kind_index]);
inter_ti V1 = P->W.instruction[index];
inter_ti V2 = P->W.instruction[index+1];
return Inter::Types::verify_inner(P, kind_symbol, V1, V2, T);
}
inter_error_message *Inter::Types::verify_inner(inter_tree_node *P, inter_symbol *kind_symbol, inter_ti V1, inter_ti V2, inter_symbols_table *scope) {
2019-02-05 02:44:07 +02:00
switch (V1) {
case LITERAL_IVAL: {
inter_data_type *idt = Inter::Kind::data_type(kind_symbol);
if (idt) {
2020-07-01 02:58:55 +03:00
long long int I = (signed_inter_ti) V2;
2020-05-11 17:21:29 +03:00
if ((I < idt->min_value) || (I > idt->max_value)) return Inode::error(P, I"value out of range", NULL);
2019-02-05 02:44:07 +02:00
return NULL;
}
return NULL;
2019-02-05 02:44:07 +02:00
}
case ALIAS_IVAL: {
2022-02-03 17:51:44 +02:00
inter_symbol *symb = InterSymbolsTable::symbol_from_ID(scope, V2);
if (symb == NULL) {
LOG("No such symbol when verifying memory inter\n");
LOG("V2 is %08x\n", V2);
LOG("IST is $4\n", scope);
LOG("(did you forget to make the package type enclosing?)\n");
2020-05-11 17:21:29 +03:00
return Inode::error(P, I"no such symbol", NULL);
}
2022-02-04 12:04:41 +02:00
if (InterSymbol::misc_but_undefined(symb)) return NULL;
2022-02-04 02:55:12 +02:00
if (InterSymbol::defined_elsewhere(symb)) return NULL;
inter_tree_node *D = InterSymbol::definition(symb);
if (D == NULL) return Inode::error(P, I"undefined symbol", InterSymbol::identifier(symb));
2019-02-05 02:44:07 +02:00
inter_data_type *idt = Inter::Kind::data_type(kind_symbol);
if (idt == unchecked_idt) return NULL;
inter_symbol *ckind_symbol = NULL;
2022-01-30 15:32:38 +02:00
if (D->W.instruction[ID_IFLD] == INSTANCE_IST) ckind_symbol = Inter::Instance::kind_of(symb);
else if (D->W.instruction[ID_IFLD] == CONSTANT_IST) ckind_symbol = Inter::Constant::kind_of(symb);
else if (D->W.instruction[ID_IFLD] == LOCAL_IST) ckind_symbol = Inter::Local::kind_of(symb);
else if (D->W.instruction[ID_IFLD] == VARIABLE_IST) ckind_symbol = Inter::Variable::kind_of(symb);
else if (D->W.instruction[ID_IFLD] == PROPERTY_IST) ckind_symbol = Inter::Property::kind_of(symb);
else return Inode::error(P, I"nonconstant symbol", InterSymbol::identifier(symb));
if ((ckind_symbol) && (Inter::Kind::is_a(ckind_symbol, kind_symbol) == FALSE)) {
LOG("cks %S, ks %S\n", InterSymbol::identifier(ckind_symbol), InterSymbol::identifier(kind_symbol));
return Inode::error(P, I"value of wrong kind", InterSymbol::identifier(symb));
2019-02-05 02:44:07 +02:00
}
return NULL;
}
case DWORD_IVAL:
case PDWORD_IVAL:
case LITERAL_TEXT_IVAL:
case REAL_IVAL:
case GLOB_IVAL:
case UNDEF_IVAL:
case DIVIDER_IVAL:
return NULL;
}
2020-05-11 17:21:29 +03:00
return Inode::error(P, I"value of unknown category", NULL);
2019-02-05 02:44:07 +02:00
}
2020-07-01 02:58:55 +03:00
inter_symbol *Inter::Types::value_to_constant_symbol_kind(inter_symbols_table *T, inter_ti V1, inter_ti V2) {
2022-02-03 17:51:44 +02:00
inter_symbol *symb = InterSymbolsTable::symbol_from_data_pair(V1, V2, T);
2019-02-05 02:44:07 +02:00
if (symb) {
inter_tree_node *D = InterSymbol::definition(symb);
if (D == NULL) return NULL;
2019-02-05 02:44:07 +02:00
inter_symbol *ckind_symbol = NULL;
2022-01-30 15:32:38 +02:00
if (D->W.instruction[ID_IFLD] == INSTANCE_IST) ckind_symbol = Inter::Instance::kind_of(symb);
else if (D->W.instruction[ID_IFLD] == CONSTANT_IST) ckind_symbol = Inter::Constant::kind_of(symb);
2019-02-05 02:44:07 +02:00
return ckind_symbol;
}
return NULL;
}
@
@e LITERAL_IVAL from 0x10000
@e LITERAL_TEXT_IVAL
@e REAL_IVAL
@e ALIAS_IVAL
@e UNDEF_IVAL
@e DWORD_IVAL
@e PDWORD_IVAL
@e GLOB_IVAL
@e DIVIDER_IVAL
=
2022-02-17 12:38:00 +02:00
void Inter::Types::write_pair(OUTPUT_STREAM, inter_tree_node *F,
2020-07-01 02:58:55 +03:00
inter_ti V1, inter_ti V2, inter_symbols_table *scope, int hex_flag) {
2019-02-05 02:44:07 +02:00
switch (V1) {
case LITERAL_IVAL:
if (hex_flag) WRITE("0x%x", V2);
else WRITE("%d", V2); break;
case REAL_IVAL:
WRITE("r\"");
2020-05-11 17:21:29 +03:00
Inter::Constant::write_text(OUT, Inode::ID_to_text(F, V2));
2019-02-05 02:44:07 +02:00
WRITE("\"");
break;
case LITERAL_TEXT_IVAL:
WRITE("\"");
2020-05-11 17:21:29 +03:00
Inter::Constant::write_text(OUT, Inode::ID_to_text(F, V2));
2019-02-05 02:44:07 +02:00
WRITE("\"");
break;
case ALIAS_IVAL: {
2022-02-11 12:48:26 +02:00
inter_symbol *symb = InterSymbolsTable::symbol_from_ID_not_following(scope, V2);
TextualInter::write_symbol(OUT, symb);
2019-02-05 02:44:07 +02:00
break;
}
case UNDEF_IVAL: WRITE("undef"); break;
case GLOB_IVAL:
WRITE("&\"");
2020-05-11 17:21:29 +03:00
Inter::Constant::write_text(OUT, Inode::ID_to_text(F, V2));
2019-02-05 02:44:07 +02:00
WRITE("\"");
break;
case DWORD_IVAL:
WRITE("dw'");
2020-05-11 17:21:29 +03:00
Inter::Constant::write_text(OUT, Inode::ID_to_text(F, V2));
2019-02-05 02:44:07 +02:00
WRITE("'");
break;
case PDWORD_IVAL:
WRITE("dwp'");
2020-05-11 17:21:29 +03:00
Inter::Constant::write_text(OUT, Inode::ID_to_text(F, V2));
2019-02-05 02:44:07 +02:00
WRITE("'");
break;
case DIVIDER_IVAL:
WRITE("^\"");
2020-05-11 17:21:29 +03:00
Inter::Constant::write_text(OUT, Inode::ID_to_text(F, V2));
2019-02-05 02:44:07 +02:00
WRITE("\"");
break;
default: WRITE("<invalid-value-type>"); break;
}
}
2022-02-11 12:48:26 +02:00
inter_error_message *Inter::Types::read(text_stream *line, inter_error_location *eloc, inter_bookmark *IBM, inter_symbol *kind_symbol, text_stream *S, inter_ti *val1, inter_ti *val2, inter_symbols_table *scope) {
inter_tree *I = InterBookmark::tree(IBM);
inter_package *pack = InterBookmark::package(IBM);
2019-02-05 02:44:07 +02:00
if (Str::eq(S, I"undef")) {
*val1 = UNDEF_IVAL; *val2 = 0; return NULL;
}
if ((Str::begins_with_wide_string(S, L"\"")) && (Str::ends_with_wide_string(S, L"\""))) {
2022-01-30 15:32:38 +02:00
*val1 = LITERAL_TEXT_IVAL; *val2 = InterWarehouse::create_text(InterTree::warehouse(I), pack);
text_stream *glob_storage = InterWarehouse::get_text(InterTree::warehouse(I), *val2);
2019-02-05 02:44:07 +02:00
return Inter::Constant::parse_text(glob_storage, S, 1, Str::len(S)-2, eloc);
}
if ((Str::begins_with_wide_string(S, L"r\"")) && (Str::ends_with_wide_string(S, L"\""))) {
2022-01-30 15:32:38 +02:00
*val1 = REAL_IVAL; *val2 = InterWarehouse::create_text(InterTree::warehouse(I), pack);
text_stream *glob_storage = InterWarehouse::get_text(InterTree::warehouse(I), *val2);
2019-02-05 02:44:07 +02:00
return Inter::Constant::parse_text(glob_storage, S, 2, Str::len(S)-2, eloc);
}
if ((Str::begins_with_wide_string(S, L"&\"")) && (Str::ends_with_wide_string(S, L"\""))) {
2022-01-30 15:32:38 +02:00
*val1 = GLOB_IVAL; *val2 = InterWarehouse::create_text(InterTree::warehouse(I), pack);
text_stream *glob_storage = InterWarehouse::get_text(InterTree::warehouse(I), *val2);
2019-02-05 02:44:07 +02:00
return Inter::Constant::parse_text(glob_storage, S, 2, Str::len(S)-2, eloc);
}
if ((Str::begins_with_wide_string(S, L"dw'")) && (Str::ends_with_wide_string(S, L"'"))) {
2022-01-30 15:32:38 +02:00
*val1 = DWORD_IVAL; *val2 = InterWarehouse::create_text(InterTree::warehouse(I), pack);
text_stream *glob_storage = InterWarehouse::get_text(InterTree::warehouse(I), *val2);
2019-02-05 02:44:07 +02:00
return Inter::Constant::parse_text(glob_storage, S, 3, Str::len(S)-2, eloc);
}
if ((Str::begins_with_wide_string(S, L"dwp'")) && (Str::ends_with_wide_string(S, L"'"))) {
2022-01-30 15:32:38 +02:00
*val1 = PDWORD_IVAL; *val2 = InterWarehouse::create_text(InterTree::warehouse(I), pack);
text_stream *glob_storage = InterWarehouse::get_text(InterTree::warehouse(I), *val2);
2019-02-05 02:44:07 +02:00
return Inter::Constant::parse_text(glob_storage, S, 4, Str::len(S)-2, eloc);
}
if ((Str::begins_with_wide_string(S, L"^\"")) && (Str::ends_with_wide_string(S, L"\""))) {
2022-01-30 15:32:38 +02:00
*val1 = DIVIDER_IVAL; *val2 = InterWarehouse::create_text(InterTree::warehouse(I), pack);
text_stream *divider_storage = InterWarehouse::get_text(InterTree::warehouse(I), *val2);
2019-02-05 02:44:07 +02:00
return Inter::Constant::parse_text(divider_storage, S, 2, Str::len(S)-2, eloc);
}
inter_data_type *idt = int32_idt;
if (kind_symbol) idt = Inter::Kind::data_type(kind_symbol);
2022-02-11 12:48:26 +02:00
if (Str::get_first_char(S) == '/') {
inter_symbol *symb = InterSymbolsTable::URL_to_symbol(I, S);
if (symb == NULL) {
TEMPORARY_TEXT(leaf)
LOOP_THROUGH_TEXT(pos, S) {
wchar_t c = Str::get(pos);
if (c == '/') Str::clear(leaf);
else PUT_TO(leaf, c);
}
if (Str::len(leaf) == 0) return Inter::Errors::quoted(I"URL ends in '/'", S, eloc);
symb = InterSymbolsTable::symbol_from_name(InterBookmark::scope(IBM), leaf);
if (!((symb) && (Wiring::is_wired_to_name(symb)) && (Str::eq(Wiring::wired_to_name(symb), S)))) {
symb = InterSymbolsTable::create_with_unique_name(InterBookmark::scope(IBM), leaf);
Wiring::wire_to_name(symb, S);
}
DISCARD_TEXT(leaf)
}
Inter::Types::symbol_to_pair(I, pack, symb, val1, val2);
return NULL;
}
2022-02-03 17:51:44 +02:00
inter_symbol *symb = InterSymbolsTable::symbol_from_name(scope, S);
2019-02-05 02:44:07 +02:00
if (symb) {
inter_tree_node *D = InterSymbol::definition(symb);
2022-02-04 12:04:41 +02:00
if (InterSymbol::misc_but_undefined(symb)) {
2022-02-04 02:55:12 +02:00
Inter::Types::symbol_to_pair(I, pack, symb, val1, val2);
2019-02-05 02:44:07 +02:00
return NULL;
}
2022-02-04 02:55:12 +02:00
if (InterSymbol::defined_elsewhere(symb)) {
Inter::Types::symbol_to_pair(I, pack, symb, val1, val2);
2019-02-05 02:44:07 +02:00
return NULL;
}
if (D == NULL) return Inter::Errors::quoted(I"undefined symbol", S, eloc);
2022-01-30 15:32:38 +02:00
if (D->W.instruction[ID_IFLD] == LOCAL_IST) {
2019-02-05 02:44:07 +02:00
inter_symbol *kind_loc = Inter::Local::kind_of(symb);
if (Inter::Kind::is_a(kind_loc, kind_symbol) == FALSE) {
text_stream *err = Str::new();
WRITE_TO(err, "local has kind %S which is not a %S",
InterSymbol::identifier(kind_loc),
InterSymbol::identifier(kind_symbol));
2019-02-05 02:44:07 +02:00
return Inter::Errors::quoted(err, S, eloc);
}
2022-02-04 02:55:12 +02:00
Inter::Types::symbol_to_pair(I, pack, symb, val1, val2);
2019-02-05 02:44:07 +02:00
return NULL;
}
2022-01-30 15:32:38 +02:00
if (D->W.instruction[ID_IFLD] == CONSTANT_IST) {
2019-02-05 02:44:07 +02:00
inter_symbol *kind_const = Inter::Constant::kind_of(symb);
if ((kind_const) && (Inter::Kind::is_a(kind_const, kind_symbol) == FALSE))
return Inter::Errors::quoted(I"symbol has the wrong kind", S, eloc);
2022-02-04 02:55:12 +02:00
Inter::Types::symbol_to_pair(I, pack, symb, val1, val2);
2019-02-05 02:44:07 +02:00
return NULL;
}
}
if (Inter::Types::is_enumerated(idt)) {
inter_error_message *E;
2022-02-11 12:48:26 +02:00
inter_symbol *symb = TextualInter::find_symbol(IBM, eloc, S, INSTANCE_IST, &E);
2019-02-05 02:44:07 +02:00
if (E) return E;
inter_tree_node *D = InterSymbol::definition(symb);
if (D == NULL) return Inter::Errors::quoted(I"undefined symbol", S, eloc);
2019-02-05 02:44:07 +02:00
inter_symbol *kind_const = Inter::Instance::kind_of(symb);
if (Inter::Kind::is_a(kind_const, kind_symbol) == FALSE) return Inter::Errors::quoted(I"symbol has the wrong kind", S, eloc);
2022-02-04 02:55:12 +02:00
Inter::Types::symbol_to_pair(I, pack, symb, val1, val2);
Inter::Types::symbol_to_pair(I, pack, symb, val1, val2);
2019-02-05 02:44:07 +02:00
return NULL;
}
2022-02-11 12:48:26 +02:00
wchar_t c = Str::get_first_char(S);
if ((c == '-') || (Characters::isdigit(c))) {
int sign = 1, base = 10, from = 0;
if (Str::prefix_eq(S, I"-", 1)) { sign = -1; from = 1; }
if (Str::prefix_eq(S, I"0b", 2)) { base = 2; from = 2; }
if (Str::prefix_eq(S, I"0x", 2)) { base = 16; from = 2; }
long long int N = 0;
LOOP_THROUGH_TEXT(pos, S) {
if (pos.index < from) continue;
int c = Str::get(pos), d = 0;
if ((c >= 'a') && (c <= 'z')) d = c-'a'+10;
else if ((c >= 'A') && (c <= 'Z')) d = c-'A'+10;
else if ((c >= '0') && (c <= '9')) d = c-'0';
else return Inter::Errors::quoted(I"bad digit", S, eloc);
if (d > base) return Inter::Errors::quoted(I"bad digit for this number base", S, eloc);
N = base*N + (long long int) d;
if (pos.index > 34) return Inter::Errors::quoted(I"value out of range", S, eloc);
}
N = sign*N;
if ((idt) && ((N < idt->min_value) || (N > idt->max_value)))
return Inter::Errors::quoted(I"value out of range", S, eloc);
*val1 = LITERAL_IVAL; *val2 = (inter_ti) N;
return NULL;
2019-02-05 02:44:07 +02:00
}
2022-02-11 12:48:26 +02:00
int ident = TRUE;
LOOP_THROUGH_TEXT(pos, S)
if ((Characters::isalpha(Str::get(pos)) == FALSE) &&
(Characters::isdigit(Str::get(pos)) == FALSE) &&
(Str::get(pos) != '_'))
ident = FALSE;
if (ident) {
inter_symbol *symb = InterSymbolsTable::create_with_unique_name(InterBookmark::scope(IBM), S);
Inter::Types::symbol_to_pair(I, pack, symb, val1, val2);
InterSymbol::set_flag(symb, SPECULATIVE_ISYMF);
return NULL;
}
return Inter::Errors::quoted(I"unrecognised value", S, eloc);
2019-02-05 02:44:07 +02:00
}
int Inter::Types::read_int_in_I6_notation(text_stream *S, inter_ti *val1, inter_ti *val2) {
2019-02-05 02:44:07 +02:00
int sign = 1, base = 10, from = 0;
if (Str::prefix_eq(S, I"-", 1)) { sign = -1; from = 1; }
if (Str::prefix_eq(S, I"$", 1)) { base = 16; from = 1; }
if (Str::prefix_eq(S, I"$$", 2)) { base = 2; from = 2; }
long long int N = 0;
LOOP_THROUGH_TEXT(pos, S) {
if (pos.index < from) continue;
int c = Str::get(pos), d = 0;
if ((c >= 'a') && (c <= 'z')) d = c-'a'+10;
else if ((c >= 'A') && (c <= 'Z')) d = c-'A'+10;
else if ((c >= '0') && (c <= '9')) d = c-'0';
else return FALSE;
if (d > base) return FALSE;
N = base*N + (long long int) d;
if (pos.index > 34) return FALSE;
}
N = sign*N;
2020-07-01 02:58:55 +03:00
*val1 = LITERAL_IVAL; *val2 = (inter_ti) N;
2019-02-05 02:44:07 +02:00
return TRUE;
}
@
@e UNCHECKED_IDT from 0x60000000
@e INT32_IDT
@e INT16_IDT
@e INT8_IDT
@e INT2_IDT
@e ENUM_IDT
@e LIST_IDT
@e COLUMN_IDT
@e TABLE_IDT
@e TEXT_IDT
@e ROUTINE_IDT
@e STRUCT_IDT
@e RELATION_IDT
@e DESCRIPTION_IDT
=
void Inter::Types::create_all(void) {
unchecked_idt = Inter::Types::create(UNCHECKED_IDT, I"unchecked", -2147483648, 2147483647, FALSE);
int32_idt = Inter::Types::create(INT32_IDT, I"int32", -2147483648, 2147483647, FALSE);
Inter::Types::create(INT16_IDT, I"int16", -32768, 32767, FALSE);
Inter::Types::create(INT8_IDT, I"int8", -128, 127, FALSE);
Inter::Types::create(INT2_IDT, I"int2", 0, 1, FALSE);
Inter::Types::create(ENUM_IDT, I"enum", 0, 2147483647, TRUE);
Inter::Types::create(LIST_IDT, I"list", -2147483648, 2147483647, FALSE);
Inter::Types::create(COLUMN_IDT, I"column", -2147483648, 2147483647, FALSE);
Inter::Types::create(TABLE_IDT, I"table", -2147483648, 2147483647, FALSE);
Inter::Types::create(TEXT_IDT, I"text", -2147483648, 2147483647, FALSE);
Inter::Types::create(ROUTINE_IDT, I"routine", -2147483648, 2147483647, FALSE);
Inter::Types::create(STRUCT_IDT, I"struct", -2147483648, 2147483647, FALSE);
Inter::Types::create(RELATION_IDT, I"relation", -2147483648, 2147483647, FALSE);
Inter::Types::create(DESCRIPTION_IDT, I"description", -2147483648, 2147483647, FALSE);
}
2022-02-04 02:55:12 +02:00
@
=
int Inter::Types::pair_holds_symbol(inter_ti val1, inter_ti val2) {
if (val1 == ALIAS_IVAL) return TRUE;
return FALSE;
}
2022-02-17 12:38:00 +02:00
void Inter::Types::symbol_to_pair(inter_tree *I, inter_package *pack, inter_symbol *S,
inter_ti *val1, inter_ti *val2) {
2022-02-04 02:55:12 +02:00
if (S == NULL) internal_error("no symbol");
*val1 = ALIAS_IVAL; *val2 = InterSymbolsTable::id_from_symbol(I, pack, S);
}
2022-02-17 12:38:00 +02:00
typedef struct inter_type {
inter_data_type *underlying_data;
inter_symbol *conceptual_type;
} inter_type;
inter_type Inter::Types::parse(inter_symbols_table *T, inter_error_location *eloc,
text_stream *text, inter_error_message **E) {
inter_type it;
it.conceptual_type = NULL;
it.underlying_data = unchecked_idt;
if (Str::len(text) > 0) {
it.conceptual_type = TextualInter::find_symbol_in_table(T, eloc, text, KIND_IST, E);
if (it.conceptual_type)
it.underlying_data = Inter::Kind::data_type(it.conceptual_type);
else {
it.underlying_data = Inter::Types::find_by_name(text);
if (it.underlying_data == NULL) {
*E = Inter::Errors::quoted(I"unrecognised data type", text, eloc);
it.underlying_data = unchecked_idt;
}
}
}
return it;
}
inter_type Inter::Types::from_symbol(inter_symbol *S) {
inter_type it;
if (S) it.underlying_data = Inter::Kind::data_type(S);
else it.underlying_data = unchecked_idt;
it.conceptual_type = S;
return it;
}
inter_symbol *Inter::Types::conceptual_type(inter_type it) {
return it.conceptual_type;
}
inter_type Inter::Types::untyped(void) {
return Inter::Types::from_symbol(NULL);
}
inter_data_type *Inter::Types::data_format(inter_type it) {
return it.underlying_data;
}
inter_type Inter::Types::from_TID(inter_tree_node *P, int field) {
inter_type it;
it.underlying_data = unchecked_idt;
it.conceptual_type = InterSymbolsTable::symbol_from_ID_at_node(P, field);
if (it.conceptual_type)
it.underlying_data = Inter::Kind::data_type(it.conceptual_type);
return it;
}
inter_ti Inter::Types::to_TID(inter_bookmark *IBM, inter_type it) {
if (it.conceptual_type)
return InterSymbolsTable::id_from_symbol_at_bookmark(IBM, it.conceptual_type);
return 0;
}
void Inter::Types::verify_type_field(inter_package *owner, inter_tree_node *P,
int field, int data_field, inter_error_message **E) {
if (P->W.instruction[field]) {
inter_symbols_table *locals = InterPackage::scope(owner);
if (locals == NULL) { *E = Inode::error(P, I"function has no symbols table", NULL); return; }
*E = Inter::Verify::symbol(owner, P, P->W.instruction[field], KIND_IST);
if (*E) return;
if (data_field >= 0) {
*E = Inter::Types::validate_local(P, data_field, field, locals);
if (*E) return;
}
}
}
void Inter::Types::write_type_field(OUTPUT_STREAM, inter_tree_node *P, int field) {
inter_type it = Inter::Types::from_TID(P, field);
if (it.conceptual_type) {
WRITE("("); TextualInter::write_symbol_from(OUT, P, field); WRITE(") ");
} else if (it.underlying_data != unchecked_idt) {
WRITE("(%S) ", it.underlying_data->reserved_word);
}
}
inter_error_message *Inter::Types::read_to_type(text_stream *line, inter_error_location *eloc,
inter_bookmark *IBM, inter_type it, text_stream *S, inter_ti *val1, inter_ti *val2,
inter_symbols_table *scope) {
return Inter::Types::read(line, eloc, IBM, it.conceptual_type, S, val1, val2, scope);
}