diff --git a/asm/qbe/qbe.go b/asm/qbe/qbe.go index 2be498b..e1867a1 100644 --- a/asm/qbe/qbe.go +++ b/asm/qbe/qbe.go @@ -22,7 +22,12 @@ func extraLabel() string { var Stub string func emitf(w io.Writer, format string, args ...any) error { - _, err := w.Write([]byte(fmt.Sprintf(format, args...))) + _, err := w.Write(fmt.Appendf(nil, format, args...)) + return err +} + +func emit(w io.Writer, content string) error { + _, err := w.Write(fmt.Append(nil, content)) return err } @@ -101,14 +106,9 @@ func emitInstruction(w io.Writer, i ttir.Instruction) error { switch i := i.(type) { case *ttir.Ret: if op := i.Op; op != nil { - if err := emitf(w, "\tret %s\n", emitOperand(i.Op)); err != nil { - return err - } + return emitf(w, "\tret %s\n", emitOperand(i.Op)) } else { - if err := emitf(w, "\tret\n"); err != nil { - return err - } - + return emitf(w, "\tret\n") } case *ttir.Binary: var inst string @@ -134,31 +134,36 @@ func emitInstruction(w io.Writer, i ttir.Instruction) error { case ast.LessThanEqual: inst = "cslel" } - if err := emitf(w, "\t%s =l %s %s, %s\n", emitOperand(i.Dst), inst, emitOperand(i.Lhs), emitOperand(i.Rhs)); err != nil { - return err - } + return emitf(w, "\t%s =l %s %s, %s\n", emitOperand(i.Dst), inst, emitOperand(i.Lhs), emitOperand(i.Rhs)) case *ttir.Copy: - if err := emitf(w, "\t%s =l copy %s\n", emitOperand(i.Dst), emitOperand(i.Src)); err != nil { - return err - } + emitf(w, "\t%s =l copy %s\n", emitOperand(i.Dst), emitOperand(i.Src)) case ttir.Label: - if err := emitf(w, "@%s\n", string(i)); err != nil { - return err - } + return emitf(w, "@%s\n", string(i)) case ttir.Jump: - if err := emitf(w, "\tjmp @%s\n", string(i)); err != nil { - return err - } + return emitf(w, "\tjmp @%s\n", string(i)) case *ttir.JumpIfNotZero: after := extraLabel() - if err := emitf(w, "\tjnz %s, @%s, @%s\n@%s\n", emitOperand(i.Value), i.Label, after, after); err != nil { - return err - } + return emitf(w, "\tjnz %s, @%s, @%s\n@%s\n", emitOperand(i.Value), i.Label, after, after) case *ttir.JumpIfZero: after := extraLabel() - if err := emitf(w, "\tjnz %s, @%s, @%s\n@%s\n", emitOperand(i.Value), after, i.Label, after); err != nil { - return err + return emitf(w, "\tjnz %s, @%s, @%s\n@%s\n", emitOperand(i.Value), after, i.Label, after) + case *ttir.Call: + b := strings.Builder{} + b.WriteRune('\t') + if i.ReturnValue != nil { + b.WriteString(emitOperand(i.ReturnValue) + " =l ") } + + b.WriteString("call $" + i.FunctionName + "(") + for j, arg := range i.Arguments { + b.WriteString("l " + emitOperand(arg)) + if j < (len(i.Arguments) - 1) { + b.WriteString(", ") + } + } + + b.WriteString(")\n") + return emit(w, b.String()) default: panic("unkown instruction") } diff --git a/parser/parser.go b/parser/parser.go index 320a874..76827db 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -454,6 +454,10 @@ func (p *Parser) parseFunctionCall() ast.Expression { p.nextToken() args = append(args, p.parseExpression(PrecLowest)) + if !p.peekTokenIs(token.Comma) { + break + } + p.nextToken() } // Move onto the ')' diff --git a/test.tt b/test.tt index 682d676..df8db15 100644 --- a/test.tt +++ b/test.tt @@ -1,17 +1,12 @@ fn main(): i64 = { - i := 5; + test2(3, 0) +}; - - if i == 5 { +fn test2(until: i64, i: i64): i64 = { + if i >= until { 0 } else { - 1 - }; - - test2(3) -}; - -fn test2(hello: i64): i64 = { - hello // Comment test + test2(until, i+1) + 1 + } }; diff --git a/ttir/emit.go b/ttir/emit.go index aab4be3..24778dd 100644 --- a/ttir/emit.go +++ b/ttir/emit.go @@ -148,6 +148,24 @@ func emitExpression(expr tast.Expression) (Operand, []Instruction) { return nil, instructions case *tast.VariableReference: return &Var{Value: expr.Identifier}, []Instruction{} + case *tast.FunctionCall: + var dst Operand + if !expr.ReturnType.IsSameType(types.Unit) { + dst = &Var{Value: temp()} + } + args := []Operand{} + + instructions := []Instruction{} + + for _, arg := range expr.Arguments { + dst, argInstructions := emitExpression(arg) + + instructions = append(instructions, argInstructions...) + args = append(args, dst) + } + + instructions = append(instructions, &Call{FunctionName: expr.Identifier, Arguments: args, ReturnValue: dst}) + return dst, instructions default: panic(fmt.Sprintf("unexpected tast.Expression: %#v", expr)) } diff --git a/ttir/ttir.go b/ttir/ttir.go index 318736a..06333fb 100644 --- a/ttir/ttir.go +++ b/ttir/ttir.go @@ -117,15 +117,20 @@ func (l Label) String() string { func (l Label) instruction() {} type Call struct { - Label string - Arguments []Operand + FunctionName string + Arguments []Operand + // NOTE: Nullable ReturnValue Operand } func (c *Call) String() string { b := strings.Builder{} - b.WriteString(c.ReturnValue.String() + " = call " + c.Label + " ") + if c.ReturnValue != nil { + b.WriteString(c.ReturnValue.String() + " = ") + } + + b.WriteString("call " + c.FunctionName + " ") for i, arg := range c.Arguments { b.WriteString(arg.String()) @@ -135,6 +140,8 @@ func (c *Call) String() string { } } + b.WriteRune('\n') + return b.String() } func (c *Call) instruction() {}