Implemented source tracking and type checking
All checks were successful
/ test (push) Successful in 21s

This commit is contained in:
Eduard Urbach 2025-06-27 00:05:16 +02:00
parent 70c2da4a4d
commit 329fcfff6f
Signed by: akyoto
GPG key ID: 49226B848C78F6C8
30 changed files with 427 additions and 125 deletions

View file

@ -1,20 +1,18 @@
package ssa
type Arguments struct {
Args []Value
}
type Arguments []Value
func (v *Arguments) Dependencies() []Value {
return v.Args
func (v Arguments) Dependencies() []Value {
return v
}
func (a Arguments) Equals(b Arguments) bool {
if len(a.Args) != len(b.Args) {
if len(a) != len(b) {
return false
}
for i := range a.Args {
if !a.Args[i].Equals(b.Args[i]) {
for i := range a {
if !a[i].Equals(b[i]) {
return false
}
}

View file

@ -5,6 +5,7 @@ import (
"git.urbach.dev/cli/q/src/expression"
"git.urbach.dev/cli/q/src/token"
"git.urbach.dev/cli/q/src/types"
)
type BinaryOperation struct {
@ -12,7 +13,7 @@ type BinaryOperation struct {
Right Value
Op token.Kind
Liveness
HasToken
Source
}
func (v *BinaryOperation) Dependencies() []Value {
@ -26,10 +27,6 @@ func (a *BinaryOperation) Equals(v Value) bool {
return false
}
if a.Source.Kind != b.Source.Kind {
return false
}
if !a.Left.Equals(b.Left) {
return false
}
@ -47,4 +44,8 @@ func (v *BinaryOperation) IsConst() bool {
func (v *BinaryOperation) String() string {
return fmt.Sprintf("%s %s %s", v.Left, expression.Operators[v.Op].Symbol, v.Right)
}
func (v *BinaryOperation) Type() types.Type {
return v.Left.Type()
}

View file

@ -1,11 +1,16 @@
package ssa
import "bytes"
import (
"bytes"
"strconv"
"git.urbach.dev/cli/q/src/types"
)
type Bytes struct {
Bytes []byte
Liveness
HasToken
Source
}
func (v *Bytes) Dependencies() []Value {
@ -27,5 +32,9 @@ func (v *Bytes) IsConst() bool {
}
func (v *Bytes) String() string {
return string(v.Bytes)
return strconv.Quote(string(v.Bytes))
}
func (v *Bytes) Type() types.Type {
return types.String
}

View file

@ -1,11 +1,15 @@
package ssa
import "fmt"
import (
"fmt"
"git.urbach.dev/cli/q/src/types"
)
type Call struct {
Arguments
Liveness
HasToken
Source
}
func (a *Call) Equals(v Value) bool {
@ -23,5 +27,15 @@ func (v *Call) IsConst() bool {
}
func (v *Call) String() string {
return fmt.Sprintf("call%v", v.Args)
return fmt.Sprintf("%s(%v)", v.Arguments[0], v.Arguments[1:])
}
func (v *Call) Type() types.Type {
typ := v.Arguments[0].(*Function).Typ
if len(typ.Output) == 0 {
return types.Void
}
return typ.Output[0]
}

View file

@ -1,9 +1,12 @@
package ssa
import "git.urbach.dev/cli/q/src/types"
type Function struct {
UniqueName string
Typ *types.Function
Liveness
HasToken
Source
}
func (v *Function) Dependencies() []Value {
@ -26,4 +29,8 @@ func (v *Function) IsConst() bool {
func (v *Function) String() string {
return v.UniqueName
}
func (v *Function) Type() types.Type {
return v.Typ
}

View file

@ -1,11 +0,0 @@
package ssa
import "git.urbach.dev/cli/q/src/token"
type HasToken struct {
Source token.Token
}
func (v *HasToken) Token() token.Token {
return v.Source
}

View file

@ -1,5 +1,7 @@
package ssa
import "git.urbach.dev/cli/q/src/types"
// IR is a list of basic blocks.
type IR struct {
Blocks []*Block
@ -39,16 +41,9 @@ func (f *IR) AppendInt(x int) *Int {
return v
}
// AppendRegister adds a new register value to the last block.
func (f *IR) AppendRegister(index int) *Parameter {
v := &Parameter{Index: uint8(index)}
f.Append(v)
return v
}
// AppendFunction adds a new function value to the last block.
func (f *IR) AppendFunction(name string) *Function {
v := &Function{UniqueName: name}
func (f *IR) AppendFunction(name string, typ *types.Function) *Function {
v := &Function{UniqueName: name, Typ: typ}
f.Append(v)
return v
}

View file

@ -2,12 +2,14 @@ package ssa
import (
"fmt"
"git.urbach.dev/cli/q/src/types"
)
type Int struct {
Int int
Liveness
HasToken
Source
}
func (v *Int) Dependencies() []Value {
@ -30,4 +32,8 @@ func (v *Int) IsConst() bool {
func (v *Int) String() string {
return fmt.Sprintf("%d", v.Int)
}
func (v *Int) Type() types.Type {
return types.AnyInt
}

View file

@ -1,11 +1,17 @@
package ssa
import "fmt"
import (
"fmt"
"git.urbach.dev/cli/q/src/types"
)
type Parameter struct {
Index uint8
Name string
Typ types.Type
Liveness
HasToken
Source
}
func (v *Parameter) Dependencies() []Value {
@ -27,5 +33,9 @@ func (v *Parameter) IsConst() bool {
}
func (v *Parameter) String() string {
return fmt.Sprintf("arg[%d]", v.Index)
return fmt.Sprintf("in[%d]", v.Index)
}
func (v *Parameter) Type() types.Type {
return v.Typ
}

View file

@ -1,10 +1,14 @@
package ssa
import "fmt"
import (
"fmt"
"git.urbach.dev/cli/q/src/types"
)
type Return struct {
Arguments
HasToken
Source
}
func (a *Return) AddUse(user Value) { panic("return is not a value") }
@ -17,12 +21,12 @@ func (a *Return) Equals(v Value) bool {
return false
}
if len(a.Args) != len(b.Args) {
if len(a.Arguments) != len(b.Arguments) {
return false
}
for i := range a.Args {
if !a.Args[i].Equals(b.Args[i]) {
for i := range a.Arguments {
if !a.Arguments[i].Equals(b.Arguments[i]) {
return false
}
}
@ -35,5 +39,9 @@ func (v *Return) IsConst() bool {
}
func (v *Return) String() string {
return fmt.Sprintf("return %v", v.Args)
return fmt.Sprintf("return %v", v.Arguments)
}
func (v *Return) Type() types.Type {
return types.Void
}

13
src/ssa/Source.go Normal file
View file

@ -0,0 +1,13 @@
package ssa
import "git.urbach.dev/cli/q/src/token"
type Source token.List
func (v Source) Start() token.Position {
return v[0].Position
}
func (v Source) End() token.Position {
return v[len(v)-1].End()
}

View file

@ -1,11 +1,15 @@
package ssa
import "fmt"
import (
"fmt"
"git.urbach.dev/cli/q/src/types"
)
type Syscall struct {
Arguments
Liveness
HasToken
Source
}
func (a *Syscall) Equals(v Value) bool {
@ -23,5 +27,9 @@ func (v *Syscall) IsConst() bool {
}
func (v *Syscall) String() string {
return fmt.Sprintf("syscall%v", v.Args)
return fmt.Sprintf("syscall(%v)", v.Arguments)
}
func (v *Syscall) Type() types.Type {
return types.Any
}

View file

@ -1,13 +1,18 @@
package ssa
import "git.urbach.dev/cli/q/src/token"
import (
"git.urbach.dev/cli/q/src/token"
"git.urbach.dev/cli/q/src/types"
)
type Value interface {
AddUse(Value)
Alive() int
Dependencies() []Value
End() token.Position
Equals(Value) bool
IsConst() bool
String() string
Token() token.Token
Start() token.Position
Type() types.Type
}