about summary refs log tree commit diff
path: root/pkg/lang/compiler/compiler.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/lang/compiler/compiler.go')
-rw-r--r--pkg/lang/compiler/compiler.go188
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
 }