github.com/coyove/nj@v0.0.0-20221110084952-c7f8db1065c3/parser/parser2.go (about) 1 package parser 2 3 import ( 4 "fmt" 5 "strconv" 6 "sync/atomic" 7 8 "github.com/coyove/nj/bas" 9 "github.com/coyove/nj/internal" 10 "github.com/coyove/nj/typ" 11 ) 12 13 var ( 14 emptyBreak = &BreakContinue{Break: true} 15 emptyProg = &Prog{} 16 zero = Primitive(bas.Int(0)) 17 one = Primitive(bas.Int(1)) 18 ) 19 20 var ( 21 Sa = &Symbol{Name: bas.Str("a!")} 22 SNil = &Symbol{Name: bas.Str("nil")} 23 ) 24 25 func (lex *Lexer) pFunc(method bool, name Token, args Node, stats Node, pos Token) Node { 26 namev := bas.Str(name.Str) 27 if lex.scanner.functions.Contains(namev) { 28 lex.Error(fmt.Sprintf("function %s already existed", name.Str)) 29 } 30 lex.scanner.functions.Set(namev, bas.Nil) 31 32 // funcname := Sym(name) 33 lex.pFindTailCall(stats) 34 35 f := &Function{Name: name.Str, Body: stats, Line: pos.Line()} 36 switch vargs := args.(type) { 37 case IdentVarargExpandList: 38 f.Args, f.Vararg, f.VargExpand = append(vargs.IdentList, randomVarname()), true, vargs.Expand 39 for i := range vargs.Expand { 40 lex.scanner.constants.Set(bas.Int(i), bas.Nil) 41 } 42 case IdentVarargList: 43 f.Args, f.Vararg = vargs.IdentList, true 44 default: 45 f.Args = args.(IdentList) 46 } 47 if method { 48 return f 49 } 50 return f // &Assign{funcname, f, pos.Line()} 51 } 52 53 func __markupFuncName(recv, name Token) Token { 54 name.Str = recv.Str + "." + name.Str 55 return name 56 } 57 58 var lambdaIndex int64 59 60 func __markupLambdaName(lambda Token) Token { 61 lambda.Str = fmt.Sprintf("lambda.%d.%d", lambda.Pos.Line, atomic.AddInt64(&lambdaIndex, 1)) 62 return lambda 63 } 64 65 func (lex *Lexer) pFindTailCall(stat Node) { 66 switch v := stat.(type) { 67 case *Call: 68 v.Op = typ.OpTailCall 69 case *Prog: 70 for i, stat := range v.Stats { 71 if i == len(v.Stats)-1 { 72 lex.pFindTailCall(stat) 73 } else if b, ok := v.Stats[i+1].(*Unary); ok && b.Op == typ.OpRet && b.A == SNil { 74 lex.pFindTailCall(stat) 75 } 76 } 77 } 78 } 79 80 func (lex *Lexer) pLoop(body ...Node) Node { 81 return &Loop{emptyProg, lex.pProg(false, body...)} 82 } 83 84 func (lex *Lexer) pForRange(v Token, start, end, step, body Node, pos Token) Node { 85 forVar := Sym(v) 86 if v, ok := step.(Primitive); ok && bas.Value(v).IsNumber() { // step is a static number, easy case 87 var cmp Node 88 if bas.Value(v).Less(bas.Int(0)) { 89 cmp = lex.pBinary(typ.OpLess, end, forVar, pos) 90 } else { 91 cmp = lex.pBinary(typ.OpLess, forVar, end, pos) 92 } 93 return lex.pProg(true, 94 &Declare{forVar, start, pos.Line()}, 95 &Loop{ 96 lex.pBinary(typ.OpInc, forVar, step, pos), 97 &If{cmp, 98 lex.pProg(false, body, lex.pBinary(typ.OpInc, forVar, step, pos)), 99 emptyBreak, 100 }, 101 }, 102 ) 103 } 104 return lex.pProg(true, 105 &Declare{forVar, start, pos.Line()}, 106 &Loop{ 107 lex.pBinary(typ.OpInc, forVar, step, pos), 108 &If{ 109 lex.pBinary(typ.OpLess, lex.Int(0), step, pos), 110 &If{ 111 lex.pBinary(typ.OpLess, forVar, end, pos), // +step 112 lex.pProg(false, body, lex.pBinary(typ.OpInc, forVar, step, pos)), 113 emptyBreak, 114 }, 115 &If{ 116 lex.pBinary(typ.OpLess, end, forVar, pos), // -step 117 lex.pProg(false, body, lex.pBinary(typ.OpInc, forVar, step, pos)), 118 emptyBreak, 119 }, 120 }, 121 }, 122 ) 123 } 124 125 func (lex *Lexer) pForIn(key, value Token, expr, body Node, pos Token) Node { 126 k, v, subject, kv := Sym(key), Sym(value), randomVarname(), randomVarname() 127 return lex.pProg(true, 128 &Declare{subject, expr, pos.Line()}, 129 &Declare{k, SNil, pos.Line()}, 130 &Declare{v, SNil, pos.Line()}, 131 &Declare{kv, SNil, pos.Line()}, 132 &Loop{ 133 emptyProg, 134 lex.pProg(false, 135 &Assign{kv, lex.pBinary(typ.OpNext, subject, kv, pos), pos.Line()}, 136 &Tenary{typ.OpLoad, kv, lex.Int(0), k, pos.Line()}, 137 &Tenary{typ.OpLoad, kv, lex.Int(1), v, pos.Line()}, 138 &If{ 139 lex.pBinary(typ.OpEq, k, SNil, pos), 140 emptyBreak, 141 body, 142 }, 143 ), 144 }, 145 ) 146 } 147 148 func (lex *Lexer) pDeclareAssign(dest []Node, src ExprList, assign bool, pos Token) Node { 149 if len(src) == 1 && len(dest) > 1 { 150 tmp := randomVarname() 151 p := (&Prog{}).Append(&Declare{tmp, src[0], pos.Line()}) 152 for i, ident := range dest { 153 op := &Tenary{typ.OpLoad, tmp, lex.Int(int64(i)), Address(typ.RegA), pos.Line()} 154 if assign { 155 p.Append(assignLoadStore(ident, op, pos)) 156 } else { 157 p.Append(&Declare{ident.(*Symbol), op, pos.Line()}) 158 } 159 } 160 return p 161 } 162 if len(dest) == 1 && len(src) == 1 { 163 if assign { 164 return assignLoadStore(dest[0], src[0], pos) 165 } 166 return &Declare{dest[0].(*Symbol), src[0], pos.Line()} 167 } 168 res := &Prog{} 169 if !assign { 170 for i, v := range dest { 171 if i >= len(src) { 172 res.Append(&Declare{v.(*Symbol), SNil, pos.Line()}) 173 } else { 174 res.Append(&Declare{v.(*Symbol), src[i], pos.Line()}) 175 } 176 } 177 } else { 178 if len(dest) != len(src) { 179 lex.Error(fmt.Sprintf("unmatched number of assignments")) 180 } 181 // a0, ..., an = b0, ..., bn 182 var tmp Release 183 for i := range dest { 184 x := randomVarname() 185 tmp = append(tmp, x) 186 res.Append(&Assign{x, src[i], pos.Line()}) 187 } 188 for i, v := range dest { 189 res.Append(assignLoadStore(v, tmp[i], pos)) 190 } 191 res.Append(tmp) 192 } 193 return res 194 } 195 196 func (lex *Lexer) pArray(list, arg Node) Node { 197 if list != nil { 198 return append(list.(ExprList), arg) 199 } 200 return ExprList([]Node{arg}) 201 } 202 203 func (lex *Lexer) pArrayN(s string) Node { 204 var args []Node 205 n, _ := strconv.Atoi(s) 206 for i := 0; i < n; i++ { 207 args = append(args, SNil) 208 } 209 return ExprList(args) 210 } 211 212 func (lex *Lexer) pObject(list, k, v Node) Node { 213 if list != nil { 214 return append(list.(ExprAssignList), [2]Node{k, v}) 215 } 216 return append((ExprAssignList)(nil), [2]Node{k, v}) 217 } 218 219 func (lex *Lexer) pEmptyArray() Node { 220 return ExprList(nil) 221 } 222 223 func (lex *Lexer) pEmptyObject() Node { 224 return ExprAssignList(nil) 225 } 226 227 func randomVarname() *Symbol { 228 return &Symbol{Name: bas.Str(internal.Unnamed())} 229 }