commit e705cf3935d68404241c324272bfa8866786a711
parent 85bac318cea174ff197ba4ad71333d79e9eb3046
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Tue, 21 Jun 2022 21:21:09 -0400
cc: add support for array assignment
int a[3] = {1, 2, 3};
Diffstat:
4 files changed, 41 insertions(+), 9 deletions(-)
diff --git a/fs/cc/ast.fs b/fs/cc/ast.fs
@@ -46,14 +46,14 @@ create bopsprectbl 1 c, 1 c, 0 c, 0 c, 2 c, 2 c, 2 c, 2 c,
8 const AST_UNARYOP \ data1=uopid
9 const AST_POSTFIXOP \ data1=popid
10 const AST_BINARYOP \ data1=bopid
-\ 11 = unused
+11 const AST_LIST \ list of lvalues or constants: {1, 2, 3}
12 const AST_IF
\ 13 = unused
14 const AST_FUNCALL \ data1=name data2=MAP_FUNCTION
ASTIDCNT stringlist astidnames
"declare" "unit" "function" "return" "constant" "stmts" "args" "lvalue"
-"unaryop" "postop" "binop" "_" "if" "_" "call"
+"unaryop" "postop" "binop" "list" "if" "_" "call"
0 value curunit \ points to current Unit, the beginning of the AST
@@ -121,6 +121,23 @@ ASTIDCNT wordtbl astdatatbl ( node -- node )
alias noop parseExpression ( tok -- node ) \ forward declaration
+\ The first '{' has already been read
+: parseList ( -- node )
+ AST_LIST createnode nextt dup S" }" s= if drop exit then
+ begin ( lnode tok ) case
+ of isIdent? ( lnode )
+ AST_LVALUE createnode swap , ( lnode lvnode ) over addnode endof
+ of parse ( lnode n )
+ AST_CONSTANT createnode swap , ( lnode cnode ) over addnode endof
+ _err
+ endcase
+ nextt case
+ S" }" of s= r~ exit endof
+ S" ," of s= endof
+ _err
+ endcase
+ nextt again ;
+
: parsePostfixOp ( tok lvnode -- node )
over S" [" s= if ( tok lvnode ) \ x[y] is the equivalent of *(x+y)
nip AST_BINARYOP createnode 0 ( + ) , ( lvnode bnode )
@@ -210,7 +227,10 @@ current to parseExpression
drop ( dnode ) dup data1 ( dnode name )
swap parentnode AST_BINARYOP newnode ( name anode ) 12 ( = ) ,
AST_LVALUE newnode ( name lvnode ) swap , parentnode ( anode )
- nextt parseExpression read; ( anode expr ) swap addnode ;
+ nextt dup S" {" s= if
+ drop parseList else
+ parseExpression then
+ read; ( anode expr-or-list ) swap addnode ;
: parseArgSpecs ( funcnode -- )
nextt '(' expectChar AST_ARGSPECS newnode nextt ( argsnode tok )
diff --git a/fs/cc/gen.fs b/fs/cc/gen.fs
@@ -177,7 +177,13 @@ ASTIDCNT wordtbl gentbl ( node -- )
selop1 gennode selop2 gennode then
bopgentblpost r> data1 wexec
r> ( selectedop ) if op1<>op2 else selop1 then ;
-'w _err ( unused )
+\ TODO: this doesn't work with lvalues yet
+:w ( List )
+ dup childcount dup 1+ 4 * scratchallot dup >r ( node len a )
+ over >r tuck ! 4 + swap firstchild begin ( a node )
+ dup data1 ( a node value ) rot tuck ! ( node a )
+ 4 + swap nextsibling next ( a node ) 2drop
+ r> constarray>op ;
:w ( If )
firstchild ?dup not if _err then dup gennode ( exprnode )
vmjz, swap ( jump_addr exprnode ) ops$
diff --git a/fs/cc/vm.fs b/fs/cc/vm.fs
@@ -77,6 +77,7 @@ $00 const VM_NONE
$01 const VM_CONSTANT \ 42
$02 const VM_STACKFRAME \ ebp+x
$03 const VM_REGISTER \ eax
+$11 const VM_CONSTARRAY \ pointer to an array with the 1st elem being length
$12 const VM_*STACKFRAME \ [ebp+x]
$13 const VM_*REGISTER \ [eax]
@@ -108,6 +109,7 @@ operands value 'curop
: hasop# optype VM_NONE = not _assert ;
: noop# optype VM_NONE = _assert ;
: const>op ( n -- ) noop# VM_CONSTANT optype! oparg! ;
+: constarray>op ( a -- ) noop# VM_CONSTARRAY optype! oparg! ;
: sf+>op ( off -- ) noop# VM_*STACKFRAME optype! oparg! ;
\ get current operand SF offset, adjusted with callsz
@@ -223,7 +225,14 @@ operands value 'curop
\ op2. In other words, perform a AST_ASSIGN with the right part as op2
\ and the left part as op1.
: vmmov,
- maybederef selop1 opAsm selop2 opAsm mov, opdeinit ;
+ selop2 optype VM_CONSTARRAY = if \ special case, we have a {1, 2, 3} assign
+ selop1 optype VM_STACKFRAME = _assert
+ *op>op selop2 oparg selop1 dup @ ( a len ) >r begin ( a )
+ opAsm 4 + dup @ i32 mov, ( a+4 ) oparg 4 + oparg! next ( a )
+ drop selop2
+ else
+ maybederef selop1 opAsm selop2 opAsm mov, then
+ opdeinit ;
\ Code generation - Unary ops
diff --git a/fs/tests/cc/test.c b/fs/tests/cc/test.c
@@ -63,9 +63,6 @@ int* ptrari(int *x) {
return x + 1;
}
int array() {
- int a[3];
- *a = 42;
- *(a+1) = 12;
- a[2] = 2;
+ int a[3] = {42, 12, 2};
return *a + a[1] - *(a+2);
}