Skip to content

Commit

Permalink
upgrade to go 1.18
Browse files Browse the repository at this point in the history
  • Loading branch information
IfanTsai committed Apr 4, 2022
1 parent 12e48e5 commit 645c9f7
Show file tree
Hide file tree
Showing 13 changed files with 133 additions and 625 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/benchmark.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.17
go-version: 1.18

- name: Benchmark
run: go test -run=none -v --cover ./... -benchmem --bench=.
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
- name: Run golangci-lint
uses: golangci/golangci-lint-action@v2
with:
version: v1.43.0
version: v1.45.2

unint-test:
name: Unint Test
Expand All @@ -29,7 +29,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.17
go-version: 1.18

- name: Test
run: go test -v -cover ./...
3 changes: 3 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ linters-settings:

linters:
disable:
- forcetypeassert
- maintidx
- varnamelen
- gochecknoglobals
- funlen
- lll # Don't complain of line too long
Expand Down
10 changes: 5 additions & 5 deletions common/symboltable.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@ package common
import "github.com/IfanTsai/jirachi/pkg/safemap"

type JSymbolTable struct {
Symbols *safemap.SafeMap
Symbols *safemap.SafeMap[any]
Parent *JSymbolTable
}

func NewJSymbolTable(parent *JSymbolTable) *JSymbolTable {
return &JSymbolTable{
Symbols: safemap.NewSafeMap(),
Symbols: safemap.NewSafeMap[any](),
Parent: parent,
}
}

func (st *JSymbolTable) Get(name interface{}) interface{} {
func (st *JSymbolTable) Get(name any) any {
symbolTable := st

for symbolTable != nil {
Expand All @@ -28,13 +28,13 @@ func (st *JSymbolTable) Get(name interface{}) interface{} {
return nil
}

func (st *JSymbolTable) Set(name, value interface{}) *JSymbolTable {
func (st *JSymbolTable) Set(name, value any) *JSymbolTable {
st.Symbols.Set(name, value)

return st
}

func (st *JSymbolTable) Remove(name interface{}) *JSymbolTable {
func (st *JSymbolTable) Remove(name any) *JSymbolTable {
st.Symbols.Del(name)

return st
Expand Down
20 changes: 10 additions & 10 deletions example.j
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,7 @@ fun fib1(n)
return res[n] # can remove the return keyword
end

# recursion
fib2 = fun(n) # anonymous function
if n <= 2 then
1
else
fib2(n - 1) + fib2(n - 2)
end
end

fib3 = fun(n)
fib2 = fun(n)
if n <= 2 then
return 1
end
Expand All @@ -37,6 +28,15 @@ fib3 = fun(n)
end
end

# recursion
fib3 = fun(n) # anonymous function
if n <= 2 then
1
else
fib3(n - 1) + fib3(n - 2)
end
end

num2str = fun(number) -> '' + number # lambda

print_fib_values = fun(fib_fun, n) # higher order function
Expand Down
5 changes: 3 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/IfanTsai/jirachi

go 1.17
go 1.18

require (
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e
Expand All @@ -18,7 +18,8 @@ require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/kr/pretty v0.1.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect
golang.org/x/exp v0.0.0-20220328175248-053ad81199eb // indirect
golang.org/x/sys v0.0.0-20220403020550-483a9cbc67c0 // indirect
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
)
485 changes: 4 additions & 481 deletions go.sum

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion interpreter/builtin.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func ExecuteLen(function *object.JBuiltInFunction, args []object.JValue) (object
func ExecuteType(function *object.JBuiltInFunction, args []object.JValue) (object.JValue, error) {
arg := args[0]

return object.NewJString(object.GetJvalueType(arg)), nil
return object.NewJString(object.GetJValueType(arg)), nil
}

func ExecuteIsNumber(function *object.JBuiltInFunction, args []object.JValue) (object.JValue, error) {
Expand Down
128 changes: 58 additions & 70 deletions interpreter/interpreter.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ import (
"fmt"
"reflect"

"golang.org/x/exp/constraints"

"github.com/IfanTsai/jirachi/pkg/safemap"

"github.com/IfanTsai/jirachi/interpreter/object"

"github.com/IfanTsai/jirachi/common"
Expand Down Expand Up @@ -175,7 +179,7 @@ func (i *JInterpreter) visitListNode(node *parser.JListNode) (object.JValue, err
}

func (i *JInterpreter) visitMapNode(node *parser.JMapNode) (object.JValue, error) {
elementMap := make(map[interface{}]object.JValue)
elementMap := safemap.NewSafeMap[object.JValue]()
for keyNode, valueNode := range node.ElementMap {
keyNodeValue, err := i.visit(keyNode)
if err != nil {
Expand All @@ -198,7 +202,7 @@ func (i *JInterpreter) visitMapNode(node *parser.JMapNode) (object.JValue, error
return nil, err
}

elementMap[keyNodeValue.GetValue()] = valueNodeValue
elementMap.Set(keyNodeValue.GetValue(), valueNodeValue)
}

return object.NewJMap(elementMap).SetJPos(node.StartPos, node.EndPos).SetJContext(i.Context), nil
Expand Down Expand Up @@ -421,7 +425,6 @@ func (i *JInterpreter) visitForExprNode(node *parser.JForExprNode) (object.JValu
}

isFloat := false
var resElementValues []object.JValue

if _, ok := startNumber.GetValue().(float64); ok {
isFloat = true
Expand All @@ -431,8 +434,6 @@ func (i *JInterpreter) visitForExprNode(node *parser.JForExprNode) (object.JValu
isFloat = true
}

var res object.JValue

if isFloat {
var start, end, step float64
if reflect.TypeOf(startNumber.GetValue()).Kind() == reflect.Int {
Expand All @@ -453,74 +454,14 @@ func (i *JInterpreter) visitForExprNode(node *parser.JForExprNode) (object.JValu
step = reflect.ValueOf(stepNumber.GetValue()).Float()
}

for j := start; ; j += step {
if (step > 0 && j >= end) || (step < 0 && j <= end) {
break
}

i.Context.SymbolTable.Set(node.Token.Value, object.NewJNumber(j))

res, err = i.visit(node.BodyNode)
if err != nil {
return nil, err
}

if i.IsBreak {
i.Reset()

break
} else if i.IsContinue {
i.Reset()

continue
} else if i.IsReturn {
return res, nil
}

resElementValues = append(resElementValues, res)
}
} else {
start := int(reflect.ValueOf(startNumber.GetValue()).Int())
end := int(reflect.ValueOf(endNumber.GetValue()).Int())
step := int(reflect.ValueOf(stepNumber.GetValue()).Int())

for j := start; ; j += step {
if (step > 0 && j >= end) || (step < 0 && j <= end) {
break
}

i.Context.SymbolTable.Set(node.Token.Value, object.NewJNumber(j))

res, err = i.visit(node.BodyNode)
if err != nil {
return nil, err
}

if i.IsBreak {
i.Reset()

break
} else if i.IsContinue {
i.Reset()

continue
} else if i.IsReturn {
return res, nil
}

resElementValues = append(resElementValues, res)
}
return executeForLoop(i, node, start, step, end)
}

if res == nil {
return object.NewJNumber(nil), nil
}
start := int(reflect.ValueOf(startNumber.GetValue()).Int())
end := int(reflect.ValueOf(endNumber.GetValue()).Int())
step := int(reflect.ValueOf(stepNumber.GetValue()).Int())

if node.IsBlockStatements {
return resElementValues[len(resElementValues)-1], nil
}

return object.NewJList(resElementValues).SetJPos(node.StartPos, node.EndPos).SetJContext(i.Context), nil
return executeForLoop(i, node, start, step, end)
}

func (i *JInterpreter) visitFunDefNode(node *parser.JFuncDefNode) (object.JValue, error) {
Expand Down Expand Up @@ -666,3 +607,50 @@ func executeFunction(function *object.JFunction, argValues []object.JValue) (obj

return NewJInterpreter(newContext).visit(function.BodyNode)
}

func executeForLoop[T constraints.Integer | constraints.Float](
i *JInterpreter,
node *parser.JForExprNode,
start, step, end T,
) (object.JValue, error) {
var resElementValues []object.JValue
var res object.JValue
var err error

for j := start; ; j += step {
if (step > 0 && j >= end) || (step < 0 && j <= end) {
break
}

i.Context.SymbolTable.Set(node.Token.Value, object.NewJNumber(j))

res, err = i.visit(node.BodyNode)
if err != nil {
return nil, err
}

if i.IsBreak {
i.Reset()

break
} else if i.IsContinue {
i.Reset()

continue
} else if i.IsReturn {
return res, nil
}

resElementValues = append(resElementValues, res)
}

if res == nil {
return object.NewJNumber(nil), nil
}

if node.IsBlockStatements {
return resElementValues[len(resElementValues)-1], nil
}

return object.NewJList(resElementValues).SetJPos(node.StartPos, node.EndPos).SetJContext(i.Context), nil
}
Loading

0 comments on commit 645c9f7

Please sign in to comment.