Skip to content

Commit

Permalink
feat, refactor: add a @assert() builtin func
Browse files Browse the repository at this point in the history
  • Loading branch information
saffage committed May 8, 2024
1 parent 38fad34 commit cdaf16e
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 56 deletions.
50 changes: 15 additions & 35 deletions checker/builtin_fns.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,61 +2,41 @@ package checker

import (
"github.com/saffage/jet/ast"
"github.com/saffage/jet/constant"
"github.com/saffage/jet/types"
)

func (check *Checker) builtInMagic(args ast.Node, scope *Scope) *TypedValue {
argList, _ := args.(*ast.ParenList)
if argList == nil {
check.errorf(args, "expected argument list")
return nil
}
func (check *Checker) builtInMagic(node *ast.ParenList, args []*TypedValue) *TypedValue {
strval := constant.AsString(args[0].Value)

arg1, _ := argList.Exprs[0].(*ast.Literal)
if arg1 == nil || arg1.Kind != ast.StringLiteral {
check.errorf(argList.Exprs[0], "expected string literal")
return nil
if strval == nil {
panic("unreachable")
}

switch arg1.Value {
switch *strval {
case "Bool":
return &TypedValue{types.NewTypeDesc(types.Primitives[types.Bool]), nil}

case "I32":
return &TypedValue{types.NewTypeDesc(types.Primitives[types.I32]), nil}

default:
check.errorf(arg1, "unknown magic '%s'", arg1.Value)
check.errorf(node.Exprs[0], "unknown magic '%s'", *strval)
return nil
}
}

func (check *Checker) builtInTypeOf(args ast.Node, scope *Scope) *TypedValue {
argList, _ := args.(*ast.ParenList)
if argList == nil {
check.errorf(args, "expected argument list")
return nil
}

t := check.typeOf(argList.Exprs[0])
if t == nil {
return nil
func (check *Checker) builtInTypeOf(node *ast.ParenList, args []*TypedValue) *TypedValue {
return &TypedValue{
Type: types.NewTypeDesc(types.SkipUntyped(args[0].Type)),
Value: nil,
}

return &TypedValue{types.NewTypeDesc(types.SkipUntyped(t)), nil}
}

func (check *Checker) builtInPrint(args ast.Node, scope *Scope) *TypedValue {
argList, _ := args.(*ast.ParenList)
if argList == nil {
check.errorf(args, "expected argument list")
return nil
}

t := check.typeOf(argList)
if t == nil {
return nil
}
func (check *Checker) builtInPrint(node *ast.ParenList, args []*TypedValue) *TypedValue {
return &TypedValue{types.Unit, nil}
}

func (check *Checker) builtInAssert(node *ast.ParenList, args []*TypedValue) *TypedValue {
return &TypedValue{types.Unit, nil}
}
10 changes: 9 additions & 1 deletion checker/builtins.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"github.com/saffage/jet/types"
)

type BuiltInFn func(args ast.Node, scope *Scope) *TypedValue
type BuiltInFn func(node *ast.ParenList, args []*TypedValue) *TypedValue

type BuiltIn struct {
name string
Expand Down Expand Up @@ -45,5 +45,13 @@ func (check *Checker) defBuiltIns() {
types.NewTuple(types.Primitives[types.Any]),
),
},
{
name: "assert",
f: check.builtInAssert,
t: types.NewFunc(
types.Unit,
types.NewTuple(types.Primitives[types.Bool]),
),
},
}
}
25 changes: 11 additions & 14 deletions checker/checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,17 @@ type Checker struct {
}

type TypeInfo struct {
Data map[ast.Node]TypedValue
Types map[ast.Node]TypedValue
Data map[ast.Node]*TypedValue
Types map[ast.Node]*TypedValue
Defs map[*ast.Ident]Symbol
}

func Check(node *ast.ModuleDecl) (*TypeInfo, []error) {
module := NewModule(Global, node)
check := &Checker{
TypeInfo: &TypeInfo{
Data: make(map[ast.Node]TypedValue),
Types: make(map[ast.Node]TypedValue),
Data: make(map[ast.Node]*TypedValue),
Types: make(map[ast.Node]*TypedValue),
Defs: make(map[*ast.Ident]Symbol),
},
module: module,
Expand Down Expand Up @@ -63,14 +63,11 @@ func Check(node *ast.ModuleDecl) (*TypeInfo, []error) {
}

// Type checks 'expr' and returns its type.
// If error was occured, result is undefined
// Also, the value of the expression will also be evaluated
// (if possible) and stored in the 'check.Types' field.
// If error was occured, result is undefined.
func (check *Checker) typeOf(expr ast.Node) types.Type {
if t, ok := check.Types[expr]; ok {
return t.Type
}

if v := check.valueOfInternal(expr); v != nil {
check.setValue(expr, *v)
if v := check.valueOf(expr); v != nil {
return v.Type
}

Expand All @@ -84,7 +81,7 @@ func (check *Checker) typeOf(expr ast.Node) types.Type {

func (check *Checker) valueOf(expr ast.Node) *TypedValue {
if t, ok := check.Types[expr]; ok {
return &t
return t
}

if value := check.valueOfInternal(expr); value != nil {
Expand All @@ -104,7 +101,7 @@ func (check *Checker) setType(expr ast.Node, t types.Type) {
assert.Ok(t != nil)

if check.Types != nil {
check.Types[expr] = TypedValue{t, nil}
check.Types[expr] = &TypedValue{t, nil}
}
}

Expand All @@ -113,7 +110,7 @@ func (check *Checker) setValue(expr ast.Node, value TypedValue) {
assert.Ok(value.Type != nil)

if check.Types != nil {
check.Types[expr] = value
check.Types[expr] = &value
}
}

Expand Down
20 changes: 15 additions & 5 deletions checker/type_resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,12 +149,17 @@ func (check *Checker) typeOfBuiltInCall(node *ast.BuiltInCall) types.Type {
return nil
}

tArgs := check.typeOfParenList(args)
tArgList := check.typeOfParenList(args)
if tArgList == nil {
return nil
}

tArgs, _ := tArgList.(*types.Tuple)
if tArgs == nil {
return nil
}

if idx, err := builtIn.t.CheckArgs(tArgs.(*types.Tuple)); err != nil {
if idx, err := builtIn.t.CheckArgs(tArgs); err != nil {
n := ast.Node(args)

if idx < len(args.Exprs) {
Expand All @@ -165,7 +170,13 @@ func (check *Checker) typeOfBuiltInCall(node *ast.BuiltInCall) types.Type {
return nil
}

value := builtIn.f(args, check.scope)
vArgs := make([]*TypedValue, tArgs.Len())

for i := range len(vArgs) {
vArgs[i] = check.Types[args.Exprs[i]]
}

value := builtIn.f(args, vArgs)
if value == nil {
return nil
}
Expand Down Expand Up @@ -375,9 +386,8 @@ func (check *Checker) typeOfBracketList(node *ast.BracketList) types.Type {
return types.NewArray(size, elemType)
}

// The result is always [*types.Tuple] or its typedesc.
func (check *Checker) typeOfParenList(node *ast.ParenList) types.Type {
// Either typedesc or tuple contructor.

if len(node.Exprs) == 0 {
return types.Unit
}
Expand Down
2 changes: 1 addition & 1 deletion checker/value.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func (check *Checker) valueOfInternal(expr ast.Node) *TypedValue {
type_ := types.FromConstant(value)

if type_ == types.Primitives[types.UntypedString] {
check.Data[node] = TypedValue{type_, value}
check.Data[node] = &TypedValue{type_, value}
}

return &TypedValue{type_, value}
Expand Down

0 comments on commit cdaf16e

Please sign in to comment.