diff options
author | pommicket <pommicket@gmail.com> | 2022-01-24 13:22:16 -0500 |
---|---|---|
committer | pommicket <pommicket@gmail.com> | 2022-01-24 13:22:16 -0500 |
commit | 46635e5748c1b150d964de8a84c1a95b4e34f411 (patch) | |
tree | 882607b69ea2208135a835054feb9a2a095d310c /05 | |
parent | 6af5b3429534bd8f370c7063fb98f7bce05a0a0d (diff) |
sizeof working?
Diffstat (limited to '05')
-rw-r--r-- | 05/main.b | 76 | ||||
-rw-r--r-- | 05/main.c | 2 | ||||
-rw-r--r-- | 05/parse.b | 103 | ||||
-rw-r--r-- | 05/preprocess.b | 1 |
4 files changed, 142 insertions, 40 deletions
@@ -17,6 +17,48 @@ global function_macros_size global object_macros global function_macros +; powers of 10, stored in the following format: +; ulong significand +; ulong exponent +; where for i = -1023..1023, powers_of_10 + 16*i points to an entry where +; 10^i = significand * 2^exponent +global powers_of_10 + +global types +global types_bytes_used +; ident list of type IDs +global typedefs + + +#include util.b +#include idents.b +#include constants.b +#include preprocess.b +#include tokenize.b +#include parse.b + +function types_init + argument _types + argument ptypes_bytes_used + local i + local p + + i = 0 + p = _types + :fill_initial_types_loop + *1p = i + p += 1 + i += 1 + if i <= 16 goto fill_initial_types_loop + p = _types + TYPE_POINTER_TO_CHAR + *1p = TYPE_POINTER + p += 1 + *1p = TYPE_CHAR + p += 1 + + *8ptypes_bytes_used = p - types + return + function fprint_token_location argument fd argument token @@ -86,24 +128,6 @@ function compile_warning byte 32 byte 0 -; powers of 10, stored in the following format: -; ulong significand -; ulong exponent -; where for i = -1023..1023, powers_of_10 + 16*i points to an entry where -; 10^i = significand * 2^exponent -global powers_of_10 - -global types -global types_bytes_used -; ident list of type IDs -global typedefs - -#include util.b -#include idents.b -#include constants.b -#include preprocess.b -#include tokenize.b -#include parse.b function main argument argv2 @@ -131,21 +155,7 @@ function main function_macros = malloc(4000000) types = malloc(16000000) - i = 0 - p = types - :fill_initial_types_loop - *1p = i - p += 1 - i += 1 - if i <= 16 goto fill_initial_types_loop - p = types + TYPE_POINTER_TO_CHAR - *1p = TYPE_POINTER - p += 1 - *1p = TYPE_CHAR - p += 1 - - types_bytes_used = p - types - + types_init(types, &types_bytes_used) input_filename = .str_default_input_filename output_filename = .str_default_output_filename @@ -3,5 +3,5 @@ long double d; } (*x)(void); */ -typedef long int unsigned Foo[0?5?0:32:0?7:8]; +typedef long int unsigned Foo[sizeof"hello"+sizeof(double[sizeof(int) * sizeof 3])]; /* */ @@ -1,3 +1,29 @@ +; is this token the start of a type? +function token_is_type + argument token + local c + c = *1token + if c == TOKEN_IDENTIFIER goto token_is_ident_type + if c == KEYWORD_UNSIGNED goto return_1 + if c == KEYWORD_CHAR goto return_1 + if c == KEYWORD_SHORT goto return_1 + if c == KEYWORD_INT goto return_1 + if c == KEYWORD_LONG goto return_1 + if c == KEYWORD_FLOAT goto return_1 + if c == KEYWORD_DOUBLE goto return_1 + if c == KEYWORD_VOID goto return_1 + if c == KEYWORD_STRUCT goto return_1 + if c == KEYWORD_UNION goto return_1 + if c == KEYWORD_ENUM goto return_1 + goto return_0 + :token_is_ident_type + token += 8 + c = *8token + local b + b = ident_list_lookup(typedefs, c) + if b != 0 goto return_1 + goto return_0 + function parse_tokens argument tokens local token @@ -268,8 +294,6 @@ function parse_type_to byte 0 :parse_function_type p = suffix + 16 - local RRR - RRR = out *1out = TYPE_FUNCTION out += 1 :function_type_loop @@ -743,7 +767,7 @@ function parse_expression :parse_expr_unary - if c == KEYWORD_SIZEOF goto parse_expr_sizeof + if c == KEYWORD_SIZEOF goto parse_sizeof *1out = unary_op_to_expression_type(c) c = *1out out += 8 @@ -798,9 +822,45 @@ function parse_expression byte 32 byte 0 - :parse_expr_sizeof - byte 0xcc ; @TODO - + :parse_sizeof + ; little hack to avoid screwing up types like double[sizeof(int)] + ; temporarily switch out types array to parse the sizeof's type + local prev_types + local prev_types_bytes_used + prev_types = types + prev_types_bytes_used = types_bytes_used + types = malloc(4000) + types_init(types, &types_bytes_used) + *1out = EXPRESSION_CONSTANT_INT + out += 4 + *1out = TYPE_UNSIGNED_LONG + out += 4 + p = best + 16 + if *1p != SYMBOL_LPAREN goto parse_sizeof_expr + p += 16 + b = token_is_type(p) + if b == 0 goto parse_sizeof_expr + ; it's a type, e.g. sizeof(int) + a = parse_type(&p, &c) + if c != 0 goto bad_expression ; e.g. sizeof(int x) + *8out = type_sizeof(a) + goto parse_sizeof_finish + :parse_sizeof_expr + ; it's an expression, e.g. sizeof(x+3) + local temp + temp = malloc(4000) + p = best + 16 + parse_expression(p, tokens_end, temp) + p = temp + 4 + *8out = type_sizeof(*4p) + free(temp) + :parse_sizeof_finish + free(types) + types = prev_types + types_bytes_used = prev_types_bytes_used + out += 8 + return out + :parse_expr_member ; -> or . p = best + 16 if *1p != TOKEN_IDENTIFIER goto bad_expression @@ -978,6 +1038,37 @@ function parse_expression :return_type_double return TYPE_DOUBLE +function type_sizeof + argument type + local p + local c + p = types + type + c = *1p + if c == TYPE_CHAR goto return_1 + if c == TYPE_UNSIGNED_CHAR goto return_1 + if c == TYPE_SHORT goto return_2 + if c == TYPE_UNSIGNED_SHORT goto return_2 + if c == TYPE_INT goto return_4 + if c == TYPE_UNSIGNED_INT goto return_4 + if c == TYPE_LONG goto return_8 + if c == TYPE_UNSIGNED_LONG goto return_8 + if c == TYPE_FLOAT goto return_4 + if c == TYPE_DOUBLE goto return_8 + if c == TYPE_VOID goto return_1 + if c == TYPE_POINTER goto return_8 + if c == TYPE_FUNCTION goto return_8 + if c == TYPE_ARRAY goto sizeof_array + byte 0xcc ; @TODO + + :sizeof_array + local n + p += 1 + n = *8p + p += 8 + p -= types + c = type_sizeof(p) + return n * c + ; evaluate an expression which can be the size of an array, e.g. ; enum { A, B, C }; ; int x[A * sizeof(float) + 3 << 5]; diff --git a/05/preprocess.b b/05/preprocess.b index 2379fec..56e552a 100644 --- a/05/preprocess.b +++ b/05/preprocess.b @@ -843,6 +843,7 @@ function translation_phase_4 macro_replacement_to_terminator(filename, line_number, &in, &p, 10) ;@TODO: there's no point in doing this until we have parsing ; we'll have to evaluate constant expressions anyways for array declarations + free(if_pptokens) fputs(2, .str_if_not_implemented) byte 0xcc :str_if_not_implemented |