needs tests/harness comp/c comp/c/ast comp/c/cexpr testbegin :c enum { ONE=1, TWO=2, THREE=3, FOUR=4 }; :c uint var1, var2, *ptr1, arr1[4], arr2[3]; :c short short1; : ast<; ast< read; ; : ?cexpr< ast<; ?cexpr ; : #iscexpr ( f -- ) not ?abort"not a cexpr" ; : noopexpr?< ast< read; noopexpr? ; \test boolops cexpr parseConstExpr 42 < 54; read; 1 #eq parseConstExpr 42 > 54; read; 0 #eq \test ?cexpr on literals ?cexpr< 42; #iscexpr 42 #eq \test ?cexpr on constant ?cexpr< FOUR; #iscexpr 4 #eq \test ?cexpr on variable ?cexpr< var1; not #true \test ?cexpr on constant binop ?cexpr< FOUR+TWO; #iscexpr 6 #eq ?cexpr< FOUR-ONE; #iscexpr 3 #eq \test ?cexpr on constant unaryop ?cexpr< -FOUR; #iscexpr -4 #eq \test that a few cases of non-cexpr fail gracefully ?cexpr< (uint)var1 & 0x2a; not #true ?cexpr< var1 / 3; not #true ?cexpr< var1 + 3; not #true ?cexpr< 3 - var2; not #true \test do pointer arithmetics on constexprs involving arrays ?cexpr< arr1 + 1; #iscexpr arr1 4+ #eq ?cexpr< 2 + arr1; #iscexpr arr1 8+ #eq ?cexpr< arr2 - arr1; #iscexpr arr2 arr1 - 4/ #eq ?cexpr< arr2 - 1; #iscexpr arr2 4- #eq \test typecasts can yield constexprs ?cexpr< (uint)arr1; #iscexpr arr1 #eq \test array literals are constexprs ?cexpr< {1, 2, 3}; #iscexpr drop \test do signed comparisons in constexprs when operands are signed ?cexpr< -TWO > FOUR; #iscexpr 1 #eq ?cexpr< (int)-TWO > (int)FOUR; #iscexpr 0 #eq \test some simple noopexprs noopexpr?< var1; #true noopexpr?< TWO; #true noopexpr?< sizeof(*ptr1); #true noopexpr?< &var1; #true \test some simple NOT noopexprs noopexpr?< var1+TWO; not #true \test noopexpr does constant-type optimizations before yielding their result noopexpr?< var1+ZERO; #true \test typecasts are never noopexprs \ for a while, I liked to think that they could, but the thing is, their base \ symbol needs to be fetched before the cast is done or else things are not good noopexpr?< (void*)var1; not #true noopexpr?< (int)var1; not #true noopexpr?< (char)var1; not #true noopexpr?< (int)short1; not #true \test deref can be a noop when it targets a i) noopexpr?< *ptr1; not #true noopexpr?< arr1[2]; #true \test deref of a *direct* structptr is a noop struct MyStruct { uint fname ; } :c void foo () { MyStruct *structptr; } noopexpr?< *structptr; #true noopexpr?< *(structptr+1); not #true \test constoptimize : chk" [rcompile] " ast<; constoptimize ['] .ast capture #s[]= ; :c uint x; chk"(sym x)" x+0; chk"(+ (sym x) (lit 00000001))" x+1; chk"(sym x)" ZERO+x; chk"(sym x)" x>>0; chk"(sym x)" x<<0; chk"(<< (lit 00000001) (sym x))" 1<