Skip to content

Commit

Permalink
Merge pull request #5 from hutcho66/negative-tests
Browse files Browse the repository at this point in the history
Negative tests
  • Loading branch information
hutcho66 committed Nov 3, 2023
2 parents b97fcd5 + 54dffa9 commit d4fc9fa
Show file tree
Hide file tree
Showing 14 changed files with 370 additions and 182 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ This is a implementation of the language in go, with a few additions:
- break and continue statements within loops
- Lambda expressions using a JavaScript style arrow syntax
- Additonal builtin functions, e.g. `len`, `map`, `filter`, `reduce`
- Classes with static, getter and setter functions


## Table of Contents
Expand Down
4 changes: 4 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ require golang.org/x/exp v0.0.0-20231006140011-7918f672742d

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fatih/color v1.15.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/stretchr/testify v1.8.4 // indirect
golang.org/x/sys v0.13.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
10 changes: 10 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
13 changes: 7 additions & 6 deletions src/pkg/interpreter/class.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package interpreter

import (
"errors"

"github.com/hutcho66/glox/src/pkg/ast"
"github.com/hutcho66/glox/src/pkg/lox_error"
"github.com/hutcho66/glox/src/pkg/token"
)

Expand Down Expand Up @@ -44,18 +45,18 @@ func (c *LoxClass) findMethod(name string) *LoxFunction {
return nil
}

func (c *LoxClass) get(name *token.Token) any {
func (c *LoxClass) get(name *token.Token) (any, error) {

method := c.findMethod(name.Lexeme)

if method == nil {
panic(lox_error.RuntimeError(name, "Undefined property '"+name.Lexeme+"'."))
if method == nil || method.declaration.Kind != ast.STATIC_METHOD {
return nil, errors.New("Undefined property '" + name.Lexeme + "'.")
}

if method.declaration.Kind != ast.STATIC_METHOD {
panic(lox_error.RuntimeError(name, "Cannot call non-static method '"+name.Lexeme+"' directly on class."))
return nil, errors.New("Cannot call non-static method '" + name.Lexeme + "' directly on class.")
}

return method.bind(c)
return method.bind(c), nil

}
19 changes: 5 additions & 14 deletions src/pkg/interpreter/environment.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package interpreter

import (
"github.com/hutcho66/glox/src/pkg/lox_error"
"github.com/hutcho66/glox/src/pkg/token"
)

Expand All @@ -24,12 +23,9 @@ func NewEnclosingEnvironment(enclosing *Environment) *Environment {
}
}

func (e *Environment) get(name *token.Token) (any, error) {
if val, ok := e.values[name.Lexeme]; ok {
return val, nil
}

return nil, lox_error.RuntimeError(name, "Undefined variable '"+name.Lexeme+"'")
func (e *Environment) get(name *token.Token) (any, bool) {
val, ok := e.values[name.Lexeme]
return val, ok
}

func (e *Environment) getAt(distance int, name string) any {
Expand All @@ -49,13 +45,8 @@ func (e *Environment) define(name string, value any) {
e.values[name] = value
}

func (e *Environment) assign(name *token.Token, value any) error {
if _, ok := e.values[name.Lexeme]; ok {
e.values[name.Lexeme] = value
return nil
}

return lox_error.RuntimeError(name, "Undefined variable '"+name.Lexeme+"'")
func (e *Environment) assign(name *token.Token, value any) {
e.values[name.Lexeme] = value
}

func (e *Environment) assignAt(distance int, name *token.Token, value any) {
Expand Down
11 changes: 6 additions & 5 deletions src/pkg/interpreter/instance.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package interpreter

import (
"github.com/hutcho66/glox/src/pkg/lox_error"
"errors"

"github.com/hutcho66/glox/src/pkg/token"
)

Expand All @@ -17,17 +18,17 @@ func NewLoxInstance(class *LoxClass) *LoxInstance {
}
}

func (i *LoxInstance) get(name *token.Token) any {
func (i *LoxInstance) get(name *token.Token) (any, error) {
if field, ok := i.Fields[name.Lexeme]; ok {
return field
return field, nil
}

method := i.Class.findMethod(name.Lexeme)
if method != nil {
return method.bind(i)
return method.bind(i), nil
}

panic(lox_error.RuntimeError(name, "Undefined property '"+name.Lexeme+"'."))
return nil, errors.New("Undefined property '" + name.Lexeme + "'.")
}

func (i *LoxInstance) set(name *token.Token, value any) {
Expand Down
Loading

0 comments on commit d4fc9fa

Please sign in to comment.