From a61c4f88f987f314a0b664b38ba86ca6cb7fea7f Mon Sep 17 00:00:00 2001
From: pommicket <pommicket@gmail.com>
Date: Sat, 5 Feb 2022 19:41:45 -0500
Subject: local variables in expressions

---
 05/constants.b |  2 ++
 05/main.c      |  1 +
 05/parse.b     | 32 +++++++++++++++++++++++++++++---
 3 files changed, 32 insertions(+), 3 deletions(-)

diff --git a/05/constants.b b/05/constants.b
index bef0245..73e321a 100644
--- a/05/constants.b
+++ b/05/constants.b
@@ -144,6 +144,7 @@
 ;    ushort (padding)
 ;    uint type
 ; immediately following the header in memory are the arguments of the expression
+;    - for local variables, the 64-bit rbp offset (number to be subtracted from rbp)
 ;    - for global variables, the 64-bit runtime address
 ;    - for constant ints, the 64-bit integral value
 ;    - for constant floats, the 64-bit double value (even if expression has type float)
@@ -156,6 +157,7 @@
 ;    - for function calls, the function, followed by each of the arguments to the function — info indicates the number of arguments
 ; File/line number are not stored in expressions.
 ; Note that string literals are stored as constant integers (you can check the type to know what it is)
+#define EXPRESSION_LOCAL_VARIABLE 199
 #define EXPRESSION_GLOBAL_VARIABLE 200
 #define EXPRESSION_CONSTANT_INT 201
 #define EXPRESSION_CONSTANT_FLOAT 202
diff --git a/05/main.c b/05/main.c
index 3386be0..8fa4dbd 100644
--- a/05/main.c
+++ b/05/main.c
@@ -19,6 +19,7 @@ int h(void) {
 	struct {
 		char a,b;
 	} P[] = {1,2,3,4,5};
+	int *Y = x;
 	static int marker = 0x12345678;
 	return 5;
 }
diff --git a/05/parse.b b/05/parse.b
index 38609e8..40f2a30 100644
--- a/05/parse.b
+++ b/05/parse.b
@@ -429,9 +429,12 @@ function parse_statement
 				if *1token == SYMBOL_LBRACE goto local_init_lbrace
 				n = token_next_semicolon_or_comma_not_in_brackets(token)
 				out -= 16
-				*8out = expressions_end
+				p = expressions_end
+				*8out = p
 				out += 16
-				expressions_end = parse_expression(token, n, expressions_end)
+				expressions_end = parse_expression(token, n, p)
+				p += 4
+				type_decay_array_to_pointer(*4p) ; fix typing for `int[] x = {5,6}; int *y = x;`
 				token = n
 				goto local_decl_continue
 			:local_init_lbrace
@@ -2428,7 +2431,10 @@ function parse_expression
 			p += n < 3
 			c = ident_list_lookup(*8p, a)
 			if c != 0 goto found_global_variable
-			; @TODO: check if it's a local variable
+			p = local_variables
+			p += n < 3
+			c = ident_list_lookup(*8p, a)
+			if c != 0 goto found_local_variable
 			n -= 1
 			if n >= 0 goto var_lookup_loop
 		
@@ -2451,6 +2457,15 @@ function parse_expression
 		:str_undeclared_variable
 			string Undeclared variable.
 			byte 0
+		:found_local_variable
+			; it's a local variable
+			*1out = EXPRESSION_LOCAL_VARIABLE
+			out += 4
+			*4out = c > 32 ; extract type
+			out += 4
+			*8out = c & 0xffffffff ; extract rbp offset
+			out += 8
+			return out
 	:expression_integer
 		*1out = EXPRESSION_CONSTANT_INT
 		p = in + 8
@@ -3379,6 +3394,7 @@ function print_expression
 	:print_expr_skip_type
 	c = *1expression
 	
+	if c == EXPRESSION_LOCAL_VARIABLE goto print_local_variable
 	if c == EXPRESSION_GLOBAL_VARIABLE goto print_global_variable
 	if c == EXPRESSION_CONSTANT_INT goto print_expr_int
 	if c == EXPRESSION_CONSTANT_FLOAT goto print_expr_float
@@ -3409,6 +3425,16 @@ function print_expression
 	:str_global_at
 		string global@
 		byte 0
+	:print_local_variable
+		puts(.str_local_prefix)
+		expression += 8
+		putn(*8expression)
+		putc('])
+		expression += 8
+		return expression
+	:str_local_prefix
+		string [rsp-
+		byte 0
 	:print_global_variable
 		puts(.str_global_at)
 		expression += 8
-- 
cgit v1.2.3