diff options
| author | 2022-08-28 09:20:07 +0200 | |
|---|---|---|
| committer | 2022-08-28 09:20:07 +0200 | |
| commit | a744bd5fcda35b086566ba961502d589eefd5fe9 (patch) | |
| tree | fd012846bbe973394966b47687ff0aeb9256a652 /src/fold.cff | |
| parent | 57e8797417578239de57d8a62d32de403a89fb34 (diff) | |
fix some fold and add def const
Diffstat (limited to 'src/fold.cff')
| -rw-r--r-- | src/fold.cff | 68 |
1 files changed, 66 insertions, 2 deletions
diff --git a/src/fold.cff b/src/fold.cff index acfd613..2e7cae3 100644 --- a/src/fold.cff +++ b/src/fold.cff @@ -106,8 +106,8 @@ fn fbinary(ex *Expr) void { if ty->is(:Bool) { ty = typeof2(l.ty, r.ty); } - numcast(l, ty); - numcast(r, ty); + if isnumtype(l.ty) { numcast(l, ty); } + if isnumtype(r.ty) { numcast(r, ty); } if op == '/' and ty->is(:Int) and ri.i == 0 { // div/0 return; @@ -124,12 +124,35 @@ fn fbinary(ex *Expr) void { case op == '/' and ty->is(:Int); ei.i = li.i / ri.i; case op == '/' and ty->is(:Flo); *ef = *lf / *rf; case op == '%' and ty == ty_u64; ei.u = li.u % ri.u; + case op == '%' and ty->is(:Int); ei.i = li.i % ri.i; case op == '&' and ty->is(:Int); ei.i = li.i & ri.i; case op == '|' and ty->is(:Int); ei.i = li.i | ri.i; case op == '^' and ty->is(:Int); ei.i = li.i ^ ri.i; case op == '<<' and ty->is(:Int); ei.i = li.i << ri.i; case op == '>>' and ty->is(:Int) and !ty.u.Int.sgn; ei.u = li.u >> ri.u; case op == '>>' and ty->is(:Int); ei.i = li.i >> ri.i; + case op == '==' and ty->is(:Flo); *eb = *lf == *rf; + case op == '==' and ty->is(:Int); *eb = li.i == ri.i; + case op == '!=' and ty->is(:Flo); *eb = *lf != *rf; + case op == '!=' and ty->is(:Int); *eb = li.i != ri.i; + case op == '<' and ty->is(:Flo); *eb = *lf < *rf; + case op == '<' and ty == ty_u64; *eb = li.u < ri.u; + case op == '<' and ty->is(:Int); *eb = li.i < ri.i; + case op == '>' and ty->is(:Flo); *eb = *lf > *rf; + case op == '>' and ty == ty_u64; *eb = li.u > ri.u; + case op == '>' and ty->is(:Int); *eb = li.i > ri.i; + case op == '<=' and ty->is(:Flo); *eb = *lf <= *rf; + case op == '<=' and ty == ty_u64; *eb = li.u <= ri.u; + case op == '<=' and ty->is(:Int); *eb = li.i <= ri.i; + case op == '>=' and ty->is(:Flo); *eb = *lf >= *rf; + case op == '>=' and ty == ty_u64; *eb = li.u >= ri.u; + case op == '>=' and ty->is(:Int); *eb = li.i >= ri.i; + + case op == '+' and l.u.#tag == :StrLit and r.u.IntLit.u <= l.u.StrLit.#len; + assert(r.u.#tag == :IntLit, "str + ?"); + ex.u = :StrLit(l.u.StrLit[r.u.IntLit.u::l.u.StrLit.#len]); + return; + case else return; } @@ -140,6 +163,38 @@ fn fbinary(ex *Expr) void { } } +fn fcond(ex *Expr) void { + let test = ex.u.Cond.test, + t = ex.u.Cond.t, + f = ex.u.Cond.f; + let fo0 = fold(test); + if !fo0 { + return; + } + let ty = ex.ty; + *ex = test.u.BoolLit ? (do fold(t); *t;) : (do fold(f); *f;); + ex.ty = ty; +} + +fn findex(ex *Expr) void { + let l = ex.u.Index.lhs, + r = ex.u.Index.rhs; + let fl = fold(l), fr = fold(r); + if !fl or !fr { + return; + } + + if l.u.#tag == :StrLit { + if r.u.IntLit.u > l.u.StrLit.#len { + return; + } + ex.u = :IntLit{l.u.StrLit[r.u.IntLit.u]}; + } else { + assert(#f,"bad"); + } + +} + extern fn fold(ex *Expr) bool { switch ex.u.#tag { case :IntLit, :FloLit, :BoolLit; @@ -155,6 +210,12 @@ extern fn fold(ex *Expr) bool { case :BinOp; fbinary(ex); + case :Cond; + fcond(ex); + + case :Index; + findex(ex); + case else; return #f; } @@ -164,6 +225,9 @@ extern fn fold(ex *Expr) bool { numcast(ex, ex.ty); return #t; + case :StrLit, :NullLit, :EnumIni; + return #t; + case else; return #f; } |