summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--05/main.b76
-rw-r--r--05/main.c2
-rw-r--r--05/parse.b103
-rw-r--r--05/preprocess.b1
4 files changed, 142 insertions, 40 deletions
diff --git a/05/main.b b/05/main.b
index 3f963b4..35733ae 100644
--- a/05/main.b
+++ b/05/main.b
@@ -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
diff --git a/05/main.c b/05/main.c
index 0f83881..245bef7 100644
--- a/05/main.c
+++ b/05/main.c
@@ -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])];
/* */
diff --git a/05/parse.b b/05/parse.b
index 01944ae..505e9f3 100644
--- a/05/parse.b
+++ b/05/parse.b
@@ -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