Skip to content

Commit

Permalink
all: refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
saffage committed May 6, 2024
1 parent 805b363 commit 484758f
Show file tree
Hide file tree
Showing 17 changed files with 685 additions and 630 deletions.
62 changes: 27 additions & 35 deletions ast/exprs.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,6 @@ package ast

import "github.com/saffage/jet/token"

// func (*BadNode) implNode() {}
// func (*Empty) implNode() {}
// func (*Ident) implNode() {}
// func (*Literal) implNode() {}
// func (*Operator) implNode() {}

// func (*BindingWithValue) implNode() {}
// func (*Binding) implNode() {}
// func (*BuiltInCall) implNode() {}
// func (*Call) implNode() {}
// func (*Index) implNode() {}
// func (*ArrayType) implNode() {}
// func (*MemberAccess) implNode() {}
// func (*PrefixOp) implNode() {}
// func (*InfixOp) implNode() {}
// func (*PostfixOp) implNode() {}

// func (*BracketList) implNode() {}
// func (*ParenList) implNode() {}
// func (*CurlyList) implNode() {}

// func (*If) implNode() {}
// func (*Else) implNode() {}

type (
BadNode struct {
Loc token.Loc // Desired location.
Expand All @@ -52,9 +28,9 @@ type (
Kind OperatorKind
}

//
//
//
//------------------------------------------------
// Composite nodes
//------------------------------------------------

// Represents `name Type`.
Binding struct {
Expand Down Expand Up @@ -94,33 +70,41 @@ type (
Args *BracketList
}

// Represents `func(x T) T` or `(T) T`.
Signature struct {
Params *ParenList
Result Node
Loc token.Loc // `func` token.
}

// Represents `x.selector`.
MemberAccess struct {
X Node
Selector Node // TODO maybe use [Ident] ?
Loc token.Loc // `.` token.
}

// Represents `!x`, where `!` is an unary operator.
// Represents `!x`, where `!` is an prefix operator.
PrefixOp struct {
X Node
Opr *Operator
}

// Represents `x ! y`, where `!` is a binary operator.
// Represents `x ! y`, where `!` is a infix operator.
InfixOp struct {
X, Y Node
Opr *Operator
}

// Represents `x!`, where `!` is a postfix operator.
PostfixOp struct {
X Node
Opr *Operator
}

//
//
//
//------------------------------------------------
// Lists
//------------------------------------------------

// Represents `[a, b, c]`.
BracketList struct {
Expand All @@ -140,9 +124,9 @@ type (
Open, Close token.Loc // `{` and `}`.
}

//
//
//
//------------------------------------------------
// Language constructions
//------------------------------------------------

If struct {
Cond Node
Expand Down Expand Up @@ -200,6 +184,14 @@ func (n *Index) LocEnd() token.Loc { return n.Args.LocEnd() }
func (n *ArrayType) Pos() token.Loc { return n.Args.Pos() }
func (n *ArrayType) LocEnd() token.Loc { return n.X.LocEnd() }

func (n *Signature) Pos() token.Loc {
if n.Loc.Line == 0 {
return n.Params.Pos()
}
return n.Loc
}
func (n *Signature) LocEnd() token.Loc { return n.Result.LocEnd() }

func (n *MemberAccess) Pos() token.Loc { return n.X.Pos() }
func (n *MemberAccess) LocEnd() token.Loc { return n.Selector.LocEnd() }

Expand Down
29 changes: 7 additions & 22 deletions ast/nodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ func (*BuiltInCall) implNode() {}
func (*Call) implNode() {}
func (*Index) implNode() {}
func (*ArrayType) implNode() {}
func (*Signature) implNode() {}
func (*MemberAccess) implNode() {}
func (*PrefixOp) implNode() {}
func (*InfixOp) implNode() {}
Expand Down Expand Up @@ -61,7 +62,6 @@ func (*CommentGroup) implNode() {}
func (*List) implNode() {}
func (*ExprList) implNode() {}
func (*AttributeList) implNode() {}
func (*Signature) implNode() {}

func (*While) implNode() {}
func (*Return) implNode() {}
Expand All @@ -78,9 +78,9 @@ type (
Comments []*Comment
}

//
//
//
//------------------------------------------------
// Helper nodes
//------------------------------------------------

// Represents sequence of nodes, separated by semicolon\new line.
List struct {
Expand All @@ -98,16 +98,9 @@ type (
Loc token.Loc // `@` token.
}

// Represents `func(x T) T` or `(T) T`.
Signature struct {
Params *ParenList
Result Node
Loc token.Loc // `func` token.
}

//
//
//
//------------------------------------------------
// Language constructions
//------------------------------------------------

While struct {
Cond Node
Expand Down Expand Up @@ -146,14 +139,6 @@ func (n *ExprList) LocEnd() token.Loc { return n.Exprs[len(n.Exprs)-1].LocEnd()
func (n *AttributeList) Pos() token.Loc { return n.Loc }
func (n *AttributeList) LocEnd() token.Loc { return n.List.LocEnd() }

func (n *Signature) Pos() token.Loc {
if n.Loc.Line == 0 {
return n.Params.Pos()
}
return n.Loc
}
func (n *Signature) LocEnd() token.Loc { return n.Result.LocEnd() }

func (n *While) Pos() token.Loc { return n.Loc }
func (n *While) LocEnd() token.Loc { return n.Body.LocEnd() }

Expand Down
12 changes: 2 additions & 10 deletions checker/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,11 @@ func (expr *Block) visit(node ast.Node) (ast.Visitor, error) {
case ast.Decl:
switch decl := node.(type) {
case *ast.VarDecl:
sym := NewVar(expr.scope, nil, decl.Binding, decl.Binding.Name)
t, err := resolveVarDecl(decl, expr.scope)
if err != nil {
if err := resolveVar(decl, expr.scope); err != nil {
return nil, err
}

sym.setType(t)

if defined := expr.scope.Define(sym); defined != nil {
return nil, errorAlreadyDefined(sym.Ident(), defined.Ident())
}

fmt.Printf(">>> def local var `%s`\n", sym.Name())
fmt.Printf(">>> def local var `%s`\n", decl.Binding.Name)

expr.t = types.Unit
return nil, nil
Expand Down
10 changes: 1 addition & 9 deletions checker/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,18 +68,10 @@ func (m *Module) visit(node ast.Node) (ast.Visitor, error) {
panic("not implemented")

case *ast.VarDecl:
sym := NewVar(m.scope, nil, decl.Binding, decl.Binding.Name)
t, err := resolveVarDecl(decl, m.scope)
if err != nil {
if err := resolveVar(decl, m.scope); err != nil {
return nil, err
}

sym.setType(t)

if defined := m.scope.Define(sym); defined != nil {
return nil, errorAlreadyDefined(sym.Ident(), defined.Ident())
}

fmt.Printf(">>> def var `%s`\n", decl.Binding.Name)

case *ast.FuncDecl:
Expand Down
103 changes: 46 additions & 57 deletions checker/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,89 +4,78 @@ import (
"fmt"

"github.com/saffage/jet/ast"
"github.com/saffage/jet/internal/assert"
"github.com/saffage/jet/types"
)

func resolveVarDecl(node *ast.VarDecl, scope *Scope) (types.Type, error) {
var t types.Type

if node.Binding.Type != nil {
tType, err := scope.TypeOf(node.Binding.Type)
if err != nil {
return tType, err
}
func resolveVar(node *ast.VarDecl, scope *Scope) error {
// 'tValue' can be nil.
tValue, err := resolveVarValue(node.Value, scope)
if err != nil {
return err
}

assert.Ok(tType != nil, fmt.Sprintf("expression '%s' should have type", node.Binding.Type))
typedesc, _ := tType.Underlying().(*types.TypeDesc)
// 'tType' must be not nil.
tType, err := resolveVarType(node.Binding.Type, tValue, scope)
if err != nil {
return err
}

if typedesc == nil {
return t, NewErrorf(node.Binding.Type, "expression is not a type (%s)", tType)
}
fmt.Printf(">>> var value '%s'\n", tValue)
fmt.Printf(">>> var type '%s'\n", tType)

t = typedesc.Base()
fmt.Printf(">>> set `%s` type `%s`\n", node.Binding.Name, t)
if tValue != nil && !tType.Equals(tValue) {
return NewErrorf(
node.Binding.Name,
"type mismatch, expected '%s', got '%s'",
tType,
tValue,
)
}

isUnknownSizedArray := false
fmt.Printf(">>> var actual type '%s'\n", tType)
sym := NewVar(scope, tType, node.Binding, node.Binding.Name)

if array := types.AsArray(t); array != nil && array.Size() == -1 {
isUnknownSizedArray = true
if defined := scope.Define(sym); defined != nil {
return errorAlreadyDefined(sym.Ident(), defined.Ident())
}

if node.Value != nil {
tValue, err := scope.TypeOf(node.Value)
return nil
}

func resolveVarValue(value ast.Node, scope *Scope) (types.Type, error) {
if value != nil {
t, err := scope.TypeOf(value)
if err != nil {
return nil, err
}

if types.IsTypeDesc(tValue) {
return nil, NewErrorf(node.Value, "expected value, got type '%s' instead", tValue.Underlying())
if types.IsTypeDesc(t) {
return nil, NewErrorf(value, "expected value, got type '%s' instead", t.Underlying())
}

tValue = types.SkipUntyped(tValue)

if t != nil && !t.Equals(tValue) {
return t, NewErrorf(node.Value, "type mismatch, expected '%s', got '%s'", t, tValue)
}
return types.SkipUntyped(t), nil
}

if array, arrayValue := types.AsArray(t), types.AsArray(tValue); isUnknownSizedArray {
if array == nil || arrayValue == nil {
panic("unreachable")
}
return nil, nil
}

t = types.NewArray(arrayValue.Size(), array.ElemType())
fmt.Printf(">>> set `%s` type `%s`\n", node.Binding.Name, t)
func resolveVarType(typeExpr ast.Node, value types.Type, scope *Scope) (types.Type, error) {
if typeExpr != nil {
t, err := scope.TypeOf(typeExpr)
if err != nil {
return t, err
}

if t == nil {
t = tValue
fmt.Printf(">>> set `%s` type `%s`\n", node.Binding.Name, t)
if typedesc := types.AsTypeDesc(t); typedesc != nil {
return typedesc.Base(), nil
}
} else if isUnknownSizedArray {
return t, NewError(node.Binding.Name, "value is required to infer array size")

return nil, NewError(typeExpr, "expression is not a type")
}

return t, nil
return value, nil
}

// func resolveVarValue(value ast.Node, scope *Scope) (types.Type, error) {
// if value == nil {
// panic("unreachable")
// }

// t, err := scope.TypeOf(value)
// if err != nil {
// return nil, err
// }

// if types.IsTypeDesc(t) {
// return nil, NewErrorf(value, "expected value, got type '%s' instead", t.Underlying())
// }

// return types.SkipUntyped(t), nil
// }

func resolveFuncDecl(sym *Func) error {
sig := sym.node.Signature
tParams := []types.Type{}
Expand Down
Loading

0 comments on commit 484758f

Please sign in to comment.