diff options
Diffstat (limited to 'pkg/lang/compiler/compiler.go')
| -rw-r--r-- | pkg/lang/compiler/compiler.go | 188 |
1 files changed, 177 insertions, 11 deletions
diff --git a/pkg/lang/compiler/compiler.go b/pkg/lang/compiler/compiler.go index bf34487..e299fdc 100644 --- a/pkg/lang/compiler/compiler.go +++ b/pkg/lang/compiler/compiler.go @@ -6,36 +6,202 @@ import ( ) type Compiler struct { - ast ast.Program + ast ast.Program + builder code.Builder } func New(ast ast.Program) *Compiler { return &Compiler{ - ast: ast, + ast: ast, + builder: code.NewBuilder(), } } func (comp *Compiler) Compile() (code.Code, error) { - bc := make([]byte, 0, 1024) - for _, stmt := range comp.ast.Stmts { + if stmt.Kind == ast.StmtKindEmpty { + continue + } + if stmt.Kind != ast.StmtKindExpr { - panic("statements other than expressions not implemented") + panic("statements other than expressions and empties not implemented") } expr := stmt.Value.(ast.StmtExpr).Value - res, err := comp.compileExpr(expr) - if err != nil { + if err := comp.compileExpr(expr); err != nil { return code.Code{}, err } + } + + return comp.builder.Build(), nil +} + +func (comp *Compiler) compileExpr(expr ast.Expr) error { + switch expr.Kind { + case ast.ExprKindBinary: + return comp.compileBinaryExpr(expr.Value.(ast.ExprBinary)) + case ast.ExprKindUnary: + return comp.compileUnaryExpr(expr.Value.(ast.ExprUnary)) + case ast.ExprKindCall: + return comp.compileCallExpr(expr.Value.(ast.ExprCall)) + case ast.ExprKindSubscription: + return comp.compileSubscriptionExpr(expr.Value.(ast.ExprSubscription)) + + case ast.ExprKindGroup: + return comp.compileGroupExpr(expr.Value.(ast.ExprGroup)) + case ast.ExprKindFnLit: + panic("not implemented") + case ast.ExprKindArrayLit: + panic("not implemented") + case ast.ExprKindIdent: + panic("not implemented") + case ast.ExprKindIntLit: + return comp.compileIntLitExpr(expr.Value.(ast.ExprIntLit)) + case ast.ExprKindFloatLit: + return comp.compileFloatLitExpr(expr.Value.(ast.ExprFloatLit)) + case ast.ExprKindStringLit: + return comp.compileStringLitExpr(expr.Value.(ast.ExprStringLit)) + case ast.ExprKindBoolLit: + return comp.compileBoolLitExpr(expr.Value.(ast.ExprBoolLit)) + case ast.ExprKindNullLit: + return comp.compileNullLitExpr(expr.Value.(ast.ExprNullLit)) + case ast.ExprKindThis: + panic("not implemented") + default: + panic("unknown expression kind") + } +} + +func (comp *Compiler) compileBinaryExpr(expr ast.ExprBinary) error { + if err := comp.compileExpr(expr.Right); err != nil { + return err + } + + if err := comp.compileExpr(expr.Left); err != nil { + return err + } + + switch expr.Op { + case ast.BinOpPlus: + comp.builder.AppendOp(code.OpAdd) + case ast.BinOpMinus: + comp.builder.AppendOp(code.OpSub) + case ast.BinOpStar: + // comp.builder.AppendOp(code.OpMul) + panic("not implemented") + case ast.BinOpSlash: + // comp.builder.AppendOp(code.OpDiv) + panic("not implemented") + case ast.BinOpPercent: + // comp.builder.AppendOp(code.OpMod) + panic("not implemented") + + case ast.BinOpAssign: + panic("not implemented") + case ast.BinOpEq: + // comp.builder.AppendOp(code.OpEq) + panic("not implemented") + case ast.BinOpNeq: + // comp.builder.AppendOp(code.OpNeq) + panic("not implemented") + case ast.BinOpLt: + // comp.builder.AppendOp(code.OpLt) + panic("not implemented") + case ast.BinOpLte: + comp.builder.AppendOp(code.OpLte) + case ast.BinOpGt: + // comp.builder.AppendOp(code.OpGt) + panic("not implemented") + case ast.BinOpGte: + // comp.builder.AppendOp(code.OpGte) + panic("not implemented") + default: + panic("unknown binary operator") + } + + return nil +} + +func (comp *Compiler) compileUnaryExpr(expr ast.ExprUnary) error { + if err := comp.compileExpr(expr.Value); err != nil { + return err + } + + switch expr.Op { + case ast.UnOpBang: + panic("not implemented") + case ast.UnOpMinus: + panic("not implemented") + default: + panic("unknown unary operator") + } + + return nil +} + +func (comp *Compiler) compileCallExpr(expr ast.ExprCall) error { + for i := len(expr.Args) - 1; i >= 0; i-- { + if err := comp.compileExpr(expr.Args[i]); err != nil { + return err + } + } + + if err := comp.compileExpr(expr.Callee); err != nil { + return err + } + + comp.builder.AppendOp(code.OpCall) + comp.builder.AppendInt(int64(len(expr.Args))) + + return nil +} + +func (comp *Compiler) compileSubscriptionExpr(expr ast.ExprSubscription) error { + if err := comp.compileExpr(expr.Key); err != nil { + return err + } - bc = append(bc, res...) + if err := comp.compileExpr(expr.Obj); err != nil { + return err } - return code.New(bc, code.NewDebugInfo("unknown file")), nil + comp.builder.AppendOp(code.OpIndex) + return nil +} + +func (comp *Compiler) compileGroupExpr(expr ast.ExprGroup) error { + return comp.compileExpr(expr.Value) +} + +func (comp *Compiler) compileIntLitExpr(expr ast.ExprIntLit) error { + comp.builder.AppendOp(code.OpPushInt) + comp.builder.AppendInt(int64(expr.Value)) + return nil +} + +func (comp *Compiler) compileFloatLitExpr(expr ast.ExprFloatLit) error { + comp.builder.AppendOp(code.OpPushFloat) + comp.builder.AppendFloat(expr.Value) + return nil +} + +func (comp *Compiler) compileStringLitExpr(expr ast.ExprStringLit) error { + comp.builder.AppendOp(code.OpPushString) + comp.builder.AppendString(expr.Value) + return nil +} + +func (comp *Compiler) compileBoolLitExpr(expr ast.ExprBoolLit) error { + if expr.Value { + comp.builder.AppendOp(code.OpPushTrue) + } else { + comp.builder.AppendOp(code.OpPushFalse) + } + return nil } -func (comp *Compiler) compileExpr(expr ast.Expr) ([]byte, error) { - panic("not implemented") +func (comp *Compiler) compileNullLitExpr(expr ast.ExprNullLit) error { + comp.builder.AppendOp(code.OpPushNull) + return nil } |
