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  }