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  }