github.com/coyove/nj@v0.0.0-20221110084952-c7f8db1065c3/parser/node.go (about) 1 package parser 2 3 import ( 4 "bytes" 5 "fmt" 6 "io" 7 "unsafe" 8 9 "github.com/coyove/nj/bas" 10 "github.com/coyove/nj/internal" 11 "github.com/coyove/nj/typ" 12 ) 13 14 type Token struct { 15 Type uint32 16 Str string 17 Pos Position 18 } 19 20 func (t *Token) Line() uint32 { 21 return t.Pos.Line 22 } 23 24 func (t *Token) String() string { 25 return t.Str 26 } 27 28 type Position struct { 29 Source string 30 Line uint32 31 Column uint32 32 } 33 34 func (pos *Position) String() string { 35 return fmt.Sprintf("%s:%d:%d", pos.Source, pos.Line, pos.Column) 36 } 37 38 type Node interface { 39 Dump(io.Writer) 40 } 41 42 type GetLine interface { 43 Node 44 GetLine() (string, int) 45 } 46 47 type Symbol struct { 48 Name bas.Value 49 Line uint32 50 } 51 52 func (s *Symbol) Dump(w io.Writer) { 53 if s.Line == 0 { 54 s.Name.Stringify(w, typ.MarshalToString) 55 } else { 56 internal.WriteString(w, fmt.Sprintf("%v/%d", s.Name, s.Line)) 57 } 58 } 59 60 func (s *Symbol) GetLine() (string, int) { 61 return s.Name.Str(), int(s.Line) 62 } 63 64 type Address uint16 65 66 func (s Address) Dump(w io.Writer) { 67 fmt.Fprintf(w, "@%08x", s) 68 } 69 70 type Prog struct { 71 DoBlock bool 72 Stats []Node 73 } 74 75 func (p *Prog) Append(stat Node) *Prog { 76 if p2, ok := stat.(*Prog); ok && !p2.DoBlock { 77 p.Stats = append(p.Stats, p2.Stats...) 78 } else { 79 p.Stats = append(p.Stats, stat) 80 } 81 return p 82 } 83 84 func (p *Prog) Dump(w io.Writer) { 85 if p == nil { 86 internal.WriteString(w, "(prog)") 87 return 88 } 89 internal.WriteString(w, internal.IfStr(p.DoBlock, "(do", "(prog")) 90 for _, stat := range p.Stats { 91 if stat != nil { 92 internal.WriteString(w, " ") 93 stat.Dump(w) 94 } 95 } 96 internal.WriteString(w, ")") 97 } 98 99 func (p *Prog) String() string { 100 buf := &bytes.Buffer{} 101 p.Dump(buf) 102 return buf.String() 103 } 104 105 type LoadConst struct { 106 Table bas.Map 107 Funcs bas.Map 108 } 109 110 func (p *LoadConst) Dump(w io.Writer) { 111 internal.WriteString(w, "(loadconst") 112 p.Table.Foreach(func(k bas.Value, v *bas.Value) bool { 113 internal.WriteString(w, " ") 114 k.Stringify(w, typ.MarshalToJSON) 115 return true 116 }) 117 p.Funcs.Foreach(func(k bas.Value, v *bas.Value) bool { 118 internal.WriteString(w, " f:") 119 k.Stringify(w, typ.MarshalToString) 120 return true 121 }) 122 internal.WriteString(w, ")") 123 } 124 125 type Primitive bas.Value 126 127 func (p Primitive) Dump(w io.Writer) { 128 bas.Value(p).Stringify(w, typ.MarshalToJSON) 129 } 130 131 func (p Primitive) Value() bas.Value { 132 return bas.Value(p) 133 } 134 135 type If struct { 136 Cond Node 137 True, False Node 138 } 139 140 func (p *If) Dump(w io.Writer) { 141 internal.WriteString(w, "(if ") 142 p.Cond.Dump(w) 143 internal.WriteString(w, " ") 144 p.True.Dump(w) 145 if p.False != nil { 146 internal.WriteString(w, " ") 147 p.False.Dump(w) 148 } 149 internal.WriteString(w, ")") 150 } 151 152 type Unary struct { 153 Op byte 154 A Node 155 Line uint32 156 } 157 158 func (b *Unary) Dump(w io.Writer) { 159 fmt.Fprintf(w, "(%s/%d ", typ.UnaryOpcode[b.Op], b.Line) 160 b.A.Dump(w) 161 internal.WriteString(w, ")") 162 } 163 164 func (b *Unary) GetLine() (string, int) { 165 return typ.UnaryOpcode[b.Op], int(b.Line) 166 } 167 168 type Binary struct { 169 A, B Node 170 Op byte 171 Line uint32 172 } 173 174 func (b *Binary) Dump(w io.Writer) { 175 fmt.Fprintf(w, "(%s/%d ", typ.BinaryOpcode[b.Op], b.Line) 176 b.A.Dump(w) 177 internal.WriteString(w, " ") 178 b.B.Dump(w) 179 internal.WriteString(w, ")") 180 } 181 182 func (b *Binary) GetLine() (string, int) { 183 return typ.BinaryOpcode[b.Op], int(b.Line) 184 } 185 186 type Declare struct { 187 Name *Symbol 188 Value Node 189 Line uint32 190 } 191 192 func (p *Declare) Dump(w io.Writer) { 193 fmt.Fprintf(w, "(declare/%d %s ", p.Line, p.Name.Name) 194 p.Value.Dump(w) 195 internal.WriteString(w, ")") 196 } 197 198 func (b *Declare) GetLine() (string, int) { 199 return b.Name.Name.Str(), int(b.Line) 200 } 201 202 type Assign Declare 203 204 func (p *Assign) Dump(w io.Writer) { 205 fmt.Fprintf(w, "(assign/%d %s ", p.Line, p.Name.Name) 206 p.Value.Dump(w) 207 internal.WriteString(w, ")") 208 } 209 210 func (b *Assign) GetLine() (string, int) { 211 return b.Name.Name.Str(), int(b.Line) 212 } 213 214 type Release []*Symbol 215 216 func (p Release) Dump(w io.Writer) { 217 internal.WriteString(w, "(release") 218 for _, name := range p { 219 internal.WriteString(w, " ") 220 name.Dump(w) 221 } 222 internal.WriteString(w, ")") 223 } 224 225 type Tenary struct { 226 Op byte 227 A, B, C Node 228 Line uint32 229 } 230 231 func (p *Tenary) Dump(w io.Writer) { 232 fmt.Fprintf(w, "(%s/%d ", typ.TenaryOpcode[p.Op], p.Line) 233 p.A.Dump(w) 234 internal.WriteString(w, " ") 235 p.B.Dump(w) 236 internal.WriteString(w, " ") 237 p.C.Dump(w) 238 internal.WriteString(w, ")") 239 } 240 241 func (b *Tenary) GetLine() (string, int) { 242 return typ.TenaryOpcode[b.Op], int(b.Line) 243 } 244 245 type IdentList []Node 246 247 func (p IdentList) Dump(w io.Writer) { 248 internal.WriteString(w, "(identlist") 249 for _, n := range p { 250 internal.WriteString(w, " ") 251 n.Dump(w) 252 } 253 internal.WriteString(w, ")") 254 } 255 256 type IdentVarargList struct { 257 IdentList 258 } 259 260 type IdentVarargExpandList struct { 261 IdentList 262 Expand IdentList 263 } 264 265 type ExprList []Node 266 267 func (p ExprList) Dump(w io.Writer) { 268 internal.WriteString(w, "(list") 269 for _, n := range p { 270 internal.WriteString(w, " ") 271 n.Dump(w) 272 } 273 internal.WriteString(w, ")") 274 } 275 276 type DeclList []Node 277 278 func (p DeclList) Dump(w io.Writer) {} 279 280 type ExprAssignList [][2]Node 281 282 func (p *ExprAssignList) ExpandAsExprList() (tmp ExprList) { 283 *(*[3]int)(unsafe.Pointer(&tmp)) = *(*[3]int)(unsafe.Pointer(p)) 284 (*(*[3]int)(unsafe.Pointer(&tmp)))[1] = len(*p) * 2 285 (*(*[3]int)(unsafe.Pointer(&tmp)))[2] = cap(*p) * 2 286 return 287 } 288 289 func (p ExprAssignList) Dump(w io.Writer) { 290 internal.WriteString(w, "(assignlist") 291 for _, n2 := range p { 292 internal.WriteString(w, " (") 293 n2[0].Dump(w) 294 internal.WriteString(w, " ") 295 n2[1].Dump(w) 296 internal.WriteString(w, ")") 297 } 298 internal.WriteString(w, ")") 299 } 300 301 type And struct { 302 A, B Node 303 } 304 305 func (p And) Dump(w io.Writer) { 306 internal.WriteString(w, "(and ") 307 p.A.Dump(w) 308 internal.WriteString(w, " ") 309 p.B.Dump(w) 310 internal.WriteString(w, ")") 311 } 312 313 type Or And 314 315 func (p Or) Dump(w io.Writer) { 316 internal.WriteString(w, "(or ") 317 p.A.Dump(w) 318 internal.WriteString(w, " ") 319 p.B.Dump(w) 320 internal.WriteString(w, ")") 321 } 322 323 type Loop struct { 324 Continue Node 325 Body Node 326 } 327 328 func (p *Loop) Dump(w io.Writer) { 329 internal.WriteString(w, "(loop ") 330 p.Continue.Dump(w) 331 internal.WriteString(w, " ") 332 p.Body.Dump(w) 333 internal.WriteString(w, ")") 334 } 335 336 type Call struct { 337 Op byte 338 Callee Node 339 Args ExprList 340 Vararg bool 341 Line uint32 342 } 343 344 func (p *Call) Dump(w io.Writer) { 345 internal.WriteString(w, "(") 346 internal.WriteString(w, internal.IfStr(p.Op == typ.OpTailCall, "tail", "")) 347 internal.WriteString(w, "call") 348 internal.WriteString(w, internal.IfStr(p.Vararg, "varg", "")) 349 fmt.Fprintf(w, "/%d ", p.Line) 350 p.Callee.Dump(w) 351 internal.WriteString(w, " ") 352 p.Args.Dump(w) 353 internal.WriteString(w, ")") 354 } 355 356 func (b *Call) GetLine() (string, int) { 357 buf := &bytes.Buffer{} 358 b.Callee.Dump(buf) 359 return buf.String(), int(b.Line) 360 } 361 362 type Function struct { 363 Name string 364 Args IdentList 365 Body Node 366 Vararg bool 367 VargExpand IdentList 368 Line uint32 369 } 370 371 func (p *Function) Dump(w io.Writer) { 372 fmt.Fprintf(w, "(function/%d %s ", p.Line, p.Name) 373 p.Args.Dump(w) 374 if p.Vararg { 375 if len(p.VargExpand) > 0 { 376 internal.WriteString(w, " (vargexpand ") 377 p.VargExpand.Dump(w) 378 internal.WriteString(w, ")") 379 } else { 380 internal.WriteString(w, " (varg)") 381 } 382 } 383 internal.WriteString(w, " ") 384 p.Body.Dump(w) 385 internal.WriteString(w, ")") 386 } 387 388 func (b *Function) GetLine() (string, int) { 389 return b.Name, int(b.Line) 390 } 391 392 type GotoLabel struct { 393 Label string 394 Goto bool 395 Line uint32 396 } 397 398 func (p *GotoLabel) Dump(w io.Writer) { 399 fmt.Fprintf(w, "(%s/%d %s)", internal.IfStr(p.Goto, "goto", "label"), p.Line, p.Label) 400 } 401 402 func (p *GotoLabel) GetLine() (string, int) { 403 return p.Label, int(p.Line) 404 } 405 406 type BreakContinue struct { 407 Break bool 408 Line uint32 409 } 410 411 func (p *BreakContinue) Dump(w io.Writer) { 412 fmt.Fprintf(w, "(%s/%d)", internal.IfStr(p.Break, "break", "continue"), p.Line) 413 } 414 415 func (p *BreakContinue) GetLine() (string, int) { 416 return internal.IfStr(p.Break, "break", "continue"), int(p.Line) 417 } 418 419 func Sym(tok Token) *Symbol { 420 return &Symbol{bas.Str(tok.Str), tok.Line()} 421 } 422 423 func (lex *Lexer) Str(s string) Primitive { 424 x := Primitive(bas.Str(s)) 425 lex.scanner.constants.Set(bas.Value(x), bas.Nil) 426 return x 427 } 428 429 func (lex *Lexer) Num(v string) Primitive { 430 f, i, isInt, err := internal.ParseNumber(v) 431 internal.PanicErr(err) 432 if isInt { 433 return lex.Int(i) 434 } 435 return lex.Float(f) 436 } 437 438 func (lex *Lexer) Int(v int64) Primitive { 439 x := Primitive(bas.Int64(v)) 440 if v != 0 && v != 1 { 441 lex.scanner.constants.Set(bas.Value(x), bas.Nil) 442 } 443 return x 444 } 445 446 func (lex *Lexer) IntBool(b bool) (n Node) { 447 if b { 448 return lex.Int(1) 449 } 450 return lex.Int(0) 451 } 452 453 func (lex *Lexer) Float(v float64) Primitive { 454 x := Primitive(bas.Float64(v)) 455 lex.scanner.constants.Set(bas.Value(x), bas.Nil) 456 return x 457 } 458 459 func pUnary(op byte, a Node, pos Token) Node { 460 return &Unary{Op: op, A: a, Line: pos.Line()} 461 } 462 463 func (lex *Lexer) pProg(do bool, n ...Node) Node { 464 return &Prog{do, n} 465 } 466 467 func (lex *Lexer) pBinary(op byte, a, b Node, pos Token) Node { 468 if op == typ.OpAdd && isString(a) && isString(b) { 469 as := bas.Value(a.(Primitive)).Str() 470 bs := bas.Value(b.(Primitive)).Str() 471 return Primitive(lex.Str(as + bs)) 472 } 473 if isNumber(a) && isNumber(b) { 474 a := bas.Value(a.(Primitive)) 475 b := bas.Value(b.(Primitive)) 476 switch op { 477 case typ.OpAdd: 478 if a.IsInt64() && b.IsInt64() { 479 return lex.Int(a.Int64() + b.Int64()) 480 } 481 return lex.Float(a.Float64() + b.Float64()) 482 483 case typ.OpSub: 484 if a.IsInt64() && b.IsInt64() { 485 return lex.Int(a.Int64() - b.Int64()) 486 } 487 return lex.Float(a.Float64() - b.Float64()) 488 case typ.OpMul: 489 // Special rules: a*1 and 1*a are omitted 490 if a != bas.Int(1) && b != bas.Int(1) { 491 if a.IsInt64() && b.IsInt64() { 492 return lex.Int(a.Int64() * b.Int64()) 493 } 494 return lex.Float(a.Float64() * b.Float64()) 495 } 496 case typ.OpDiv: 497 return lex.Float(a.Float64() / b.Float64()) 498 case typ.OpIDiv: 499 if b != bas.Int(0) { 500 return lex.Int(a.Int64() / b.Int64()) 501 } 502 case typ.OpMod: 503 if b != bas.Int(0) { 504 return lex.Int(a.Int64() % b.Int64()) 505 } 506 case typ.OpLessEq: 507 if a.Equal(b) { 508 return lex.IntBool(true) 509 } 510 fallthrough 511 case typ.OpLess: 512 if a.IsInt64() && b.IsInt64() { 513 return lex.IntBool(a.Int64() < b.Int64()) 514 } 515 return lex.IntBool(a.Float64() < b.Float64()) 516 case typ.OpEq: 517 return lex.IntBool(a.Equal(b)) 518 case typ.OpNeq: 519 return lex.IntBool(!a.Equal(b)) 520 } 521 } 522 return &Binary{Op: op, A: a, B: b, Line: pos.Line()} 523 } 524 525 func (lex *Lexer) pBitwise(op byte, a, b Node, pos Token) Node { 526 if isInt64(a) && isInt64(b) { 527 a := bas.Value(a.(Primitive)) 528 b := bas.Value(b.(Primitive)) 529 switch op { 530 case typ.OpExtBitAnd: 531 return lex.Int(a.Int64() & b.Int64()) 532 case typ.OpExtBitOr: 533 return lex.Int(a.Int64() | b.Int64()) 534 case typ.OpExtBitXor: 535 return lex.Int(a.Int64() ^ b.Int64()) 536 case typ.OpExtBitLsh: 537 return lex.Int(a.Int64() << b.Int64()) 538 case typ.OpExtBitRsh: 539 return lex.Int(a.Int64() >> b.Int64()) 540 case typ.OpExtBitURsh: 541 return lex.Int(int64(uint64(a.Int64()) >> b.Int64())) 542 } 543 } 544 return &Binary{Op: op, A: a, B: b, Line: pos.Line()} 545 } 546 547 func assignLoadStore(n, v Node, pos Token) Node { 548 if load, ok := n.(*Tenary); ok && load.Op == typ.OpLoad { 549 return &Tenary{typ.OpStore, load.A, load.B, v, pos.Line()} 550 } 551 return &Assign{n.(*Symbol), v, pos.Line()} 552 } 553 554 func isString(n Node) bool { 555 n2, ok := n.(Primitive) 556 return ok && bas.Value(n2).IsString() 557 } 558 559 func isNumber(n Node) bool { 560 n2, ok := n.(Primitive) 561 return ok && bas.Value(n2).IsNumber() 562 } 563 564 func isInt64(n Node) bool { 565 n2, ok := n.(Primitive) 566 return ok && bas.Value(n2).IsInt64() 567 }