enums almost working

This commit is contained in:
pommicket 2022-01-24 20:53:37 -05:00
parent 150fbb9dd8
commit 049bd1440d
5 changed files with 142 additions and 9 deletions

View file

@ -201,6 +201,7 @@
; array of n t's: TYPE_ARRAY {n as 8 bytes} t ; array of n t's: TYPE_ARRAY {n as 8 bytes} t
; struct/union: TYPE_STRUCT/TYPE_UNION {0 for incomplete types/4-byte pointer to struct/union} ; struct/union: TYPE_STRUCT/TYPE_UNION {0 for incomplete types/4-byte pointer to struct/union}
; function: TYPE_FUNCTION {arg1 type} {arg2 type} ... {argn type} 0 {return type} ; function: TYPE_FUNCTION {arg1 type} {arg2 type} ... {argn type} 0 {return type}
; note that enum types are just treated as ints.
#define TYPE_VOID 1 #define TYPE_VOID 1
#define TYPE_CHAR 3 #define TYPE_CHAR 3
#define TYPE_UNSIGNED_CHAR 4 #define TYPE_UNSIGNED_CHAR 4

View file

@ -1,5 +1,4 @@
; an "identifier list" is a list of identifiers and 64-bit values associated with them ; an "identifier list" is a list of identifiers and 64-bit values associated with them.
; the values should be non-zero because 0 is returned for undefined identifiers.
function ident_list_create function ident_list_create
argument nbytes argument nbytes
@ -35,6 +34,23 @@ function ident_list_lookup
if b == 0 goto ilist_lookup_loop if b == 0 goto ilist_lookup_loop
return *8list ; UNALIGNED return *8list ; UNALIGNED
; if identifier in list, sets *pvalue to its value (if pvalue is not null) and returns 1
; otherwise, returns 0
function ident_list_lookup_check
argument list
argument ident
argument pvalue
local b
:ilist_lookcheck_loop
if *1list == 255 goto return_0
b = str_equals(list, ident)
list = memchr(list, 0)
list += 1
if b == 0 goto ilist_lookcheck_loop
if pvalue == 0 goto return_1
*8pvalue = *8list
return 1
function ident_list_print function ident_list_print
argument list argument list
:ilist_print_loop :ilist_print_loop

View file

@ -28,7 +28,8 @@ global types
global types_bytes_used global types_bytes_used
; ident list of type IDs ; ident list of type IDs
global typedefs global typedefs
; ident list of enum values
global enumerators
#include util.b #include util.b
#include idents.b #include idents.b
@ -145,6 +146,7 @@ function main
fill_in_powers_of_10() fill_in_powers_of_10()
typedefs = ident_list_create(100000) typedefs = ident_list_create(100000)
enumerators = ident_list_create(400000)
dat_banned_objmacros = 255 dat_banned_objmacros = 255
dat_banned_fmacros = 255 dat_banned_fmacros = 255

View file

@ -4,3 +4,10 @@
} (*x)(void); } (*x)(void);
*/ */
typedef int Foo[(char)((unsigned char)0xff + (unsigned char)0xf02)]; typedef int Foo[(char)((unsigned char)0xff + (unsigned char)0xf02)];
typedef enum {
HELLO,
THERE,
TEST = 1-3,
EEE
} y;
typedef int Bar[EEE];

View file

@ -164,6 +164,7 @@ function parse_type_to
local prefix_end local prefix_end
local suffix local suffix
local suffix_end local suffix_end
local expr
token = *8p_token token = *8p_token
prefix = token prefix = token
@ -297,7 +298,7 @@ function parse_type_to
types = malloc(4000) types = malloc(4000)
types_init(types, &types_bytes_used) types_init(types, &types_bytes_used)
local expr
expr = malloc(4000) expr = malloc(4000)
*1out = TYPE_ARRAY *1out = TYPE_ARRAY
out += 1 out += 1
@ -305,8 +306,8 @@ function parse_type_to
token_skip_to_matching_rsquare(&p) token_skip_to_matching_rsquare(&p)
suffix += 16 ; skip [ suffix += 16 ; skip [
parse_expression(suffix, p, expr) parse_expression(suffix, p, expr)
print_expression(expr) ;print_expression(expr)
putc(10) ;putc(10)
evaluate_constant_expression(*8p_token, expr, &n) evaluate_constant_expression(*8p_token, expr, &n)
if n < 0 goto bad_array_size if n < 0 goto bad_array_size
*8out = n *8out = n
@ -458,7 +459,91 @@ function parse_type_to
:base_type_union :base_type_union
byte 0xcc ; @TODO byte 0xcc ; @TODO
:base_type_enum :base_type_enum
byte 0xcc ; @TODO local q
*1out = TYPE_INT ; treat any enum as int
out += 1
types_bytes_used = out - types
p = prefix + 16
if *1p == SYMBOL_LBRACE goto enum_definition
if *1p != TOKEN_IDENTIFIER goto bad_type ; e.g. enum int x;
p += 16
if *1p == SYMBOL_LBRACE goto enum_definition
goto base_type_done ; just using an enum type, not defining it.
:enum_definition
local name
local value
value = -1 ; consider initial previous value as -1, because -1 + 1 = 0
p += 16 ; skip opening {
:enum_defn_loop
if *1p == SYMBOL_RBRACE goto enum_defn_loop_end
if *1p != TOKEN_IDENTIFIER goto bad_enum_definition
p += 8
name = *8p
p += 8
if *1p == SYMBOL_COMMA goto enum_defn_no_equals
if *1p == SYMBOL_RBRACE goto enum_defn_no_equals
if *1p != SYMBOL_EQ goto bad_enum_definition ; e.g. enum { X ! };
; value provided, e.g. X = 5,
p += 16
depth = 0 ; parenthesis depth
q = p
; find matching comma -- yes, a comma can appear in an enumerator expression, e.g.
; enum { X = sizeof(struct{int x, y;}) };
; or enum { X = (enum {A,B})3 };
; find associated comma or right-brace
:enum_comma_loop
if depth > 0 goto enum_comma_deep
if *1q == SYMBOL_COMMA goto enum_comma_loop_end
if *1q == SYMBOL_RBRACE goto enum_comma_loop_end
:enum_comma_deep
if *1q == TOKEN_EOF goto bad_type
c = *1q
q += 16
if c == SYMBOL_LPAREN goto enum_comma_incdepth
if c == SYMBOL_RPAREN goto enum_comma_decdepth
goto enum_comma_loop
:enum_comma_incdepth
depth += 1
goto enum_comma_loop
:enum_comma_decdepth
depth -= 1
goto enum_comma_loop
:enum_comma_loop_end
expr = malloc(4000)
parse_expression(p, q, expr)
evaluate_constant_expression(p, expr, &value)
free(expr)
if value < -0x80000000 goto bad_enumerator
if value > 0x7fffffff goto bad_enumerator
ident_list_add(enumerators, name, value)
p = q
if *1p == SYMBOL_RBRACE goto enum_defn_loop_end
p += 16 ; skip ,
goto enum_defn_loop
:bad_enumerator
token_error(p, .str_bad_enumerator)
:str_bad_enumerator
string Enumerators too large for int.
byte 0
:enum_defn_no_equals
; no value provided, e.g. X,
; the value of this enumerator is one more than the value of the last one
value += 1
ident_list_add(enumerators, name, value)
if *1p == SYMBOL_RBRACE goto enum_defn_loop_end
p += 16 ; skip ,
goto enum_defn_loop
:enum_defn_loop_end
out = types + types_bytes_used ; fix stuff in case there were any types in the enumerator expressions
goto base_type_done
:bad_enum_definition
token_error(*8p_token, .str_bad_enum_defn)
:str_bad_enum_defn
string Bad enum definition.
byte 0
:base_type_float :base_type_float
*1out = TYPE_FLOAT *1out = TYPE_FLOAT
out += 1 out += 1
@ -989,8 +1074,30 @@ function parse_expression
if c == TOKEN_CONSTANT_CHAR goto expression_integer ; character constants are basically the same as integer constants if c == TOKEN_CONSTANT_CHAR goto expression_integer ; character constants are basically the same as integer constants
if c == TOKEN_CONSTANT_FLOAT goto expression_float if c == TOKEN_CONSTANT_FLOAT goto expression_float
if c == TOKEN_STRING_LITERAL goto expression_string_literal if c == TOKEN_STRING_LITERAL goto expression_string_literal
if c == TOKEN_IDENTIFIER goto expression_identifier
goto unrecognized_expression goto unrecognized_expression
:expression_identifier
in += 8
a = *8in
in += 8
; check if it's an enumerator
c = ident_list_lookup_check(enumerators, a, &n)
if c == 0 goto not_enumerator
; it is an enumerator
*1out = EXPRESSION_CONSTANT_INT
out += 4
*4out = TYPE_INT
out += 4
*8out = n
out += 16
return out
:not_enumerator
in -= 16
token_error(in, .str_undeclared_variable)
:str_undeclared_variable
string Undeclared variable.
byte 0
:expression_integer :expression_integer
*1out = EXPRESSION_CONSTANT_INT *1out = EXPRESSION_CONSTANT_INT
p = in + 8 p = in + 8
@ -1113,7 +1220,7 @@ function type_sizeof
; @NONSTANDARD: doesn't handle floats, but really why would you use floats in an array size ; @NONSTANDARD: doesn't handle floats, but really why would you use floats in an array size
; e.g. SomeType x[(int)3.3]; ; e.g. SomeType x[(int)3.3];
; this is also used for #if evaluation ; this is also used for #if evaluation
; tokens is used for error messages (e.g. if this "constant" expression is *x or something) ; token is used for error messages (e.g. if this "constant" expression is *x or something)
; NOTE: this returns the end of the expression, not the value (which is stored in *8p_value) ; NOTE: this returns the end of the expression, not the value (which is stored in *8p_value)
function evaluate_constant_expression function evaluate_constant_expression
argument token argument token