aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ast/modify.go36
-rw-r--r--ast/modify_test.go7
-rw-r--r--evaluator/evaluator.go2
-rw-r--r--evaluator/evaluator_test.go77
-rw-r--r--evaluator/macro_expansion.go4
-rw-r--r--evaluator/macro_expansion_test.go18
-rw-r--r--evaluator/quote_unquote_test.go16
-rw-r--r--go.mod2
-rw-r--r--lexer/lexer.go2
-rw-r--r--lexer/lexer_test.go8
-rw-r--r--main.go10
-rw-r--r--object/object.go3
-rw-r--r--object/objecttype_string.go18
-rw-r--r--parser/parser.go21
-rw-r--r--parser/parser_test.go173
-rw-r--r--parser/parser_tracing.go7
-rw-r--r--repl/face.txt13
-rw-r--r--repl/repl.go28
-rw-r--r--token/token.go2
-rw-r--r--token/tokentype_string.go42
20 files changed, 240 insertions, 249 deletions
diff --git a/ast/modify.go b/ast/modify.go
index ad50d0d..0d9a987 100644
--- a/ast/modify.go
+++ b/ast/modify.go
@@ -7,57 +7,57 @@ func Modify(node Node, modifier ModifierFunc) Node {
case *Program:
for i, statement := range node.Statements {
- node.Statements[i], _ = Modify(statement, modifier).(Statement)
+ node.Statements[i] = Modify(statement, modifier).(Statement)
}
case *ExpressionStatement:
- node.Expression, _ = Modify(node.Expression, modifier).(Expression)
+ node.Expression = Modify(node.Expression, modifier).(Expression)
case *InfixExpression:
- node.Left, _ = Modify(node.Left, modifier).(Expression)
- node.Right, _ = Modify(node.Right, modifier).(Expression)
+ node.Left = Modify(node.Left, modifier).(Expression)
+ node.Right = Modify(node.Right, modifier).(Expression)
case *PrefixExpression:
- node.Right, _ = Modify(node.Right, modifier).(Expression)
+ node.Right = Modify(node.Right, modifier).(Expression)
case *IndexExpression:
- node.Left, _ = Modify(node.Left, modifier).(Expression)
- node.Index, _ = Modify(node.Index, modifier).(Expression)
+ node.Left = Modify(node.Left, modifier).(Expression)
+ node.Index = Modify(node.Index, modifier).(Expression)
case *IfExpression:
- node.Condition, _ = Modify(node.Condition, modifier).(Expression)
- node.Consequence, _ = Modify(node.Consequence, modifier).(*BlockStatement)
+ node.Condition = Modify(node.Condition, modifier).(Expression)
+ node.Consequence = Modify(node.Consequence, modifier).(*BlockStatement)
if node.Alternative != nil {
- node.Alternative, _ = Modify(node.Alternative, modifier).(*BlockStatement)
+ node.Alternative = Modify(node.Alternative, modifier).(*BlockStatement)
}
case *BlockStatement:
for i := range node.Statements {
- node.Statements[i], _ = Modify(node.Statements[i], modifier).(Statement)
+ node.Statements[i] = Modify(node.Statements[i], modifier).(Statement)
}
case *ReturnStatement:
- node.ReturnValue, _ = Modify(node.ReturnValue, modifier).(Expression)
+ node.ReturnValue = Modify(node.ReturnValue, modifier).(Expression)
case *LetStatement:
- node.Value, _ = Modify(node.Value, modifier).(Expression)
+ node.Value = Modify(node.Value, modifier).(Expression)
case *FunctionLiteral:
for i := range node.Parameters {
- node.Parameters[i], _ = Modify(node.Parameters[i], modifier).(*Identifier)
+ node.Parameters[i] = Modify(node.Parameters[i], modifier).(*Identifier)
}
- node.Body, _ = Modify(node.Body, modifier).(*BlockStatement)
+ node.Body = Modify(node.Body, modifier).(*BlockStatement)
case *ArrayLiteral:
for i := range node.Elements {
- node.Elements[i], _ = Modify(node.Elements[i], modifier).(Expression)
+ node.Elements[i] = Modify(node.Elements[i], modifier).(Expression)
}
case *HashLiteral:
newPairs := make(map[Expression]Expression)
for key, val := range node.Pairs {
- newKey, _ := Modify(key, modifier).(Expression)
- newVal, _ := Modify(val, modifier).(Expression)
+ newKey := Modify(key, modifier).(Expression)
+ newVal := Modify(val, modifier).(Expression)
newPairs[newKey] = newVal
}
node.Pairs = newPairs
diff --git a/ast/modify_test.go b/ast/modify_test.go
index 6b5019f..6a96539 100644
--- a/ast/modify_test.go
+++ b/ast/modify_test.go
@@ -125,8 +125,7 @@ func TestModify(t *testing.T) {
equal := reflect.DeepEqual(modified, tt.expected)
if !equal {
- t.Errorf("not equal. got=%#v, want=%#v",
- modified, tt.expected)
+ t.Errorf("not equal. got=%#v, want=%#v", modified, tt.expected)
}
}
@@ -140,11 +139,11 @@ func TestModify(t *testing.T) {
Modify(hashLiteral, turnOneIntoTwo)
for key, val := range hashLiteral.Pairs {
- key, _ := key.(*IntegerLiteral)
+ key := key.(*IntegerLiteral)
if key.Value != 2 {
t.Errorf("value is not %d, got=%d", 2, key.Value)
}
- val, _ := val.(*IntegerLiteral)
+ val := val.(*IntegerLiteral)
if val.Value != 2 {
t.Errorf("value is not %d, got=%d", 2, val.Value)
}
diff --git a/evaluator/evaluator.go b/evaluator/evaluator.go
index e7b7193..c9d13d7 100644
--- a/evaluator/evaluator.go
+++ b/evaluator/evaluator.go
@@ -300,7 +300,7 @@ func isTruthy(obj object.Object) bool {
}
}
-func newError(format string, a ...interface{}) *object.Error {
+func newError(format string, a ...any) *object.Error {
return &object.Error{Message: fmt.Sprintf(format, a...)}
}
diff --git a/evaluator/evaluator_test.go b/evaluator/evaluator_test.go
index f8fb53b..f7c235d 100644
--- a/evaluator/evaluator_test.go
+++ b/evaluator/evaluator_test.go
@@ -31,7 +31,7 @@ func TestEvalIntegerExpression(t *testing.T) {
}
for _, tt := range tests {
- evaluated := testEval(tt.input)
+ evaluated := testEval(t, tt.input)
testIntegerObject(t, evaluated, tt.expected)
}
}
@@ -67,7 +67,7 @@ func TestEvalBooleanExpression(t *testing.T) {
}
for _, tt := range tests {
- evaluated := testEval(tt.input)
+ evaluated := testEval(t, tt.input)
testBooleanObject(t, evaluated, tt.expected)
}
}
@@ -86,7 +86,7 @@ func TestBangOperator(t *testing.T) {
}
for _, tt := range tests {
- evaluated := testEval(tt.input)
+ evaluated := testEval(t, tt.input)
testBooleanObject(t, evaluated, tt.expected)
}
}
@@ -94,7 +94,7 @@ func TestBangOperator(t *testing.T) {
func TestIfElseExpressions(t *testing.T) {
tests := []struct {
input string
- expected interface{}
+ expected any
}{
{"if (true) { 10 }", 10},
{"if (false) { 10 }", nil},
@@ -106,7 +106,7 @@ func TestIfElseExpressions(t *testing.T) {
}
for _, tt := range tests {
- evaluated := testEval(tt.input)
+ evaluated := testEval(t, tt.input)
integer, ok := tt.expected.(int)
if ok {
testIntegerObject(t, evaluated, int64(integer))
@@ -160,7 +160,7 @@ f(10);`,
}
for _, tt := range tests {
- evaluated := testEval(tt.input)
+ evaluated := testEval(t, tt.input)
testIntegerObject(t, evaluated, tt.expected)
}
}
@@ -229,18 +229,16 @@ if (10 > 1) {
}
for _, tt := range tests {
- evaluated := testEval(tt.input)
+ evaluated := testEval(t, tt.input)
errObj, ok := evaluated.(*object.Error)
if !ok {
- t.Errorf("no error object returned. got=%T(%+v)",
- evaluated, evaluated)
+ t.Errorf("no error object returned. got=%T(%+v)", evaluated, evaluated)
continue
}
if errObj.Message != tt.expectedMessage {
- t.Errorf("wrong error message. expected=%q, got=%q",
- tt.expectedMessage, errObj.Message)
+ t.Errorf("wrong error message. expected=%q, got=%q", tt.expectedMessage, errObj.Message)
}
}
}
@@ -257,22 +255,21 @@ func TestLetStatements(t *testing.T) {
}
for _, tt := range tests {
- testIntegerObject(t, testEval(tt.input), tt.expected)
+ testIntegerObject(t, testEval(t, tt.input), tt.expected)
}
}
func TestFunctionObject(t *testing.T) {
input := "fn(x) { x + 2; };"
- evaluated := testEval(input)
+ evaluated := testEval(t, input)
fn, ok := evaluated.(*object.Function)
if !ok {
t.Fatalf("object is not Function. got=%T (%+v)", evaluated, evaluated)
}
if len(fn.Parameters) != 1 {
- t.Fatalf("function has wrong parameters. Parameters=%+v",
- fn.Parameters)
+ t.Fatalf("function has wrong parameters. Parameters=%+v", fn.Parameters)
}
if fn.Parameters[0].String() != "x" {
@@ -300,7 +297,7 @@ func TestFunctionApplication(t *testing.T) {
}
for _, tt := range tests {
- testIntegerObject(t, testEval(tt.input), tt.expected)
+ testIntegerObject(t, testEval(t, tt.input), tt.expected)
}
}
@@ -318,7 +315,7 @@ let ourFunction = fn(first) {
ourFunction(20) + first + second;`
- testIntegerObject(t, testEval(input), 70)
+ testIntegerObject(t, testEval(t, input), 70)
}
func TestClosures(t *testing.T) {
@@ -330,13 +327,13 @@ let newAdder = fn(x) {
let addTwo = newAdder(2);
addTwo(2);`
- testIntegerObject(t, testEval(input), 4)
+ testIntegerObject(t, testEval(t, input), 4)
}
func TestStringLiteral(t *testing.T) {
input := `"Hello World!"`
- evaluated := testEval(input)
+ evaluated := testEval(t, input)
str, ok := evaluated.(*object.String)
if !ok {
t.Fatalf("object is not String. got=%T (%+v)", evaluated, evaluated)
@@ -350,7 +347,7 @@ func TestStringLiteral(t *testing.T) {
func TestStringConcatenation(t *testing.T) {
input := `"Hello" + " " + "World!"`
- evaluated := testEval(input)
+ evaluated := testEval(t, input)
str, ok := evaluated.(*object.String)
if !ok {
t.Fatalf("object is not String. got=%T (%+v)", evaluated, evaluated)
@@ -364,7 +361,7 @@ func TestStringConcatenation(t *testing.T) {
func TestBuiltinFunctions(t *testing.T) {
tests := []struct {
input string
- expected interface{}
+ expected any
}{
{`len("")`, 0},
{`len("four")`, 4},
@@ -387,7 +384,7 @@ func TestBuiltinFunctions(t *testing.T) {
}
for _, tt := range tests {
- evaluated := testEval(tt.input)
+ evaluated := testEval(t, tt.input)
switch expected := tt.expected.(type) {
case int:
@@ -397,13 +394,11 @@ func TestBuiltinFunctions(t *testing.T) {
case string:
errObj, ok := evaluated.(*object.Error)
if !ok {
- t.Errorf("object is not Error. got=%T (%+v)",
- evaluated, evaluated)
+ t.Errorf("object is not Error. got=%T (%+v)", evaluated, evaluated)
continue
}
if errObj.Message != expected {
- t.Errorf("wrong error message. expected=%q, got=%q",
- expected, errObj.Message)
+ t.Errorf("wrong error message. expected=%q, got=%q", expected, errObj.Message)
}
case []int:
array, ok := evaluated.(*object.Array)
@@ -413,8 +408,7 @@ func TestBuiltinFunctions(t *testing.T) {
}
if len(array.Elements) != len(expected) {
- t.Errorf("wrong num of elements. want=%d, got=%d",
- len(expected), len(array.Elements))
+ t.Errorf("wrong num of elements. want=%d, got=%d", len(expected), len(array.Elements))
continue
}
@@ -428,15 +422,14 @@ func TestBuiltinFunctions(t *testing.T) {
func TestArrayLiterals(t *testing.T) {
input := "[1, 2 * 2, 3 + 3]"
- evaluated := testEval(input)
+ evaluated := testEval(t, input)
result, ok := evaluated.(*object.Array)
if !ok {
t.Fatalf("object is not Array. got=%T (%+v)", evaluated, evaluated)
}
if len(result.Elements) != 3 {
- t.Fatalf("array has wrong num of elements. got=%d",
- len(result.Elements))
+ t.Fatalf("array has wrong num of elements. got=%d", len(result.Elements))
}
testIntegerObject(t, result.Elements[0], 1)
@@ -447,7 +440,7 @@ func TestArrayLiterals(t *testing.T) {
func TestArrayIndexExpressions(t *testing.T) {
tests := []struct {
input string
- expected interface{}
+ expected any
}{
{
"[1, 2, 3][0]",
@@ -492,7 +485,7 @@ func TestArrayIndexExpressions(t *testing.T) {
}
for _, tt := range tests {
- evaluated := testEval(tt.input)
+ evaluated := testEval(t, tt.input)
integer, ok := tt.expected.(int)
if ok {
testIntegerObject(t, evaluated, int64(integer))
@@ -513,7 +506,7 @@ func TestHashLiterals(t *testing.T) {
false: 6
}`
- evaluated := testEval(input)
+ evaluated := testEval(t, input)
result, ok := evaluated.(*object.Hash)
if !ok {
t.Fatalf("Eval didn't return Hash. got=%T (%+v)", evaluated, evaluated)
@@ -545,7 +538,7 @@ func TestHashLiterals(t *testing.T) {
func TestHashIndexExpressions(t *testing.T) {
tests := []struct {
input string
- expected interface{}
+ expected any
}{
{
`{"foo": 5}["foo"]`,
@@ -578,7 +571,7 @@ func TestHashIndexExpressions(t *testing.T) {
}
for _, tt := range tests {
- evaluated := testEval(tt.input)
+ evaluated := testEval(t, tt.input)
integer, ok := tt.expected.(int)
if ok {
testIntegerObject(t, evaluated, int64(integer))
@@ -587,7 +580,8 @@ func TestHashIndexExpressions(t *testing.T) {
}
}
}
-func testEval(input string) object.Object {
+func testEval(t *testing.T, input string) object.Object {
+ t.Helper()
l := lexer.New(input)
p := parser.New(l)
program := p.ParseProgram()
@@ -597,14 +591,14 @@ func testEval(input string) object.Object {
}
func testIntegerObject(t *testing.T, obj object.Object, expected int64) bool {
+ t.Helper()
result, ok := obj.(*object.Integer)
if !ok {
t.Errorf("object is not Integer. got=%T (%+v)", obj, obj)
return false
}
if result.Value != expected {
- t.Errorf("object has wrong value. got=%d, want=%d",
- result.Value, expected)
+ t.Errorf("object has wrong value. got=%d, want=%d", result.Value, expected)
return false
}
@@ -612,20 +606,21 @@ func testIntegerObject(t *testing.T, obj object.Object, expected int64) bool {
}
func testBooleanObject(t *testing.T, obj object.Object, expected bool) bool {
+ t.Helper()
result, ok := obj.(*object.Boolean)
if !ok {
t.Errorf("object is not Boolean. got=%T (%+v)", obj, obj)
return false
}
if result.Value != expected {
- t.Errorf("object has wrong value. got=%t, want=%t",
- result.Value, expected)
+ t.Errorf("object has wrong value. got=%t, want=%t", result.Value, expected)
return false
}
return true
}
func testNullObject(t *testing.T, obj object.Object) bool {
+ t.Helper()
if obj != NULL {
t.Errorf("object is not NULL. got=%T (%+v)", obj, obj)
return false
diff --git a/evaluator/macro_expansion.go b/evaluator/macro_expansion.go
index 21d3dcb..d504d31 100644
--- a/evaluator/macro_expansion.go
+++ b/evaluator/macro_expansion.go
@@ -35,8 +35,8 @@ func isMacroDefinition(node ast.Statement) bool {
}
func addMacro(stmt ast.Statement, env *object.Environment) {
- letStatement, _ := stmt.(*ast.LetStatement)
- macroLiteral, _ := letStatement.Value.(*ast.MacroLiteral)
+ letStatement := stmt.(*ast.LetStatement)
+ macroLiteral := letStatement.Value.(*ast.MacroLiteral)
macro := &object.Macro{
Parameters: macroLiteral.Parameters,
diff --git a/evaluator/macro_expansion_test.go b/evaluator/macro_expansion_test.go
index 81c03ef..df0042d 100644
--- a/evaluator/macro_expansion_test.go
+++ b/evaluator/macro_expansion_test.go
@@ -17,13 +17,12 @@ let mymacro = macro(x, y) { x + y; };
`
env := object.NewEnvironment()
- program := testParseProgram(input)
+ program := testParseProgram(t, input)
DefineMacros(program, env)
if len(program.Statements) != 2 {
- t.Fatalf("Wrong number of statements. got=%d",
- len(program.Statements))
+ t.Fatalf("Wrong number of statements. got=%d", len(program.Statements))
}
_, ok := env.Get("number")
@@ -46,8 +45,7 @@ let mymacro = macro(x, y) { x + y; };
}
if len(macro.Parameters) != 2 {
- t.Fatalf("Wrong number of macro parameters. got=%d",
- len(macro.Parameters))
+ t.Fatalf("Wrong number of macro parameters. got=%d", len(macro.Parameters))
}
if macro.Parameters[0].String() != "x" {
@@ -64,7 +62,8 @@ let mymacro = macro(x, y) { x + y; };
}
}
-func testParseProgram(input string) *ast.Program {
+func testParseProgram(t *testing.T, input string) *ast.Program {
+ t.Helper()
l := lexer.New(input)
p := parser.New(l)
return p.ParseProgram()
@@ -109,16 +108,15 @@ func TestExpandMacros(t *testing.T) {
}
for _, tt := range tests {
- expected := testParseProgram(tt.expected)
- program := testParseProgram(tt.input)
+ expected := testParseProgram(t, tt.expected)
+ program := testParseProgram(t, tt.input)
env := object.NewEnvironment()
DefineMacros(program, env)
expanded := ExpandMacros(program, env)
if expanded.String() != expected.String() {
- t.Errorf("not equal. want=%q, got=%q",
- expected.String(), expanded.String())
+ t.Errorf("not equal. want=%q, got=%q", expected.String(), expanded.String())
}
}
}
diff --git a/evaluator/quote_unquote_test.go b/evaluator/quote_unquote_test.go
index 0f79589..edcff16 100644
--- a/evaluator/quote_unquote_test.go
+++ b/evaluator/quote_unquote_test.go
@@ -30,11 +30,10 @@ func TestQuote(t *testing.T) {
}
for _, tt := range tests {
- evaluated := testEval(tt.input)
+ evaluated := testEval(t, tt.input)
quote, ok := evaluated.(*object.Quote)
if !ok {
- t.Fatalf("expected *object.Quote. got=%T (%+v)",
- evaluated, evaluated)
+ t.Fatalf("expected *object.Quote. got=%T (%+v)", evaluated, evaluated)
}
if quote.Node == nil {
@@ -42,8 +41,7 @@ func TestQuote(t *testing.T) {
}
if quote.Node.String() != tt.expected {
- t.Errorf("not equal. got=%q, want=%q",
- quote.Node.String(), tt.expected)
+ t.Errorf("not equal. got=%q, want=%q", quote.Node.String(), tt.expected)
}
}
}
@@ -99,11 +97,10 @@ func TestQuoteUnquote(t *testing.T) {
}
for _, tt := range tests {
- evaluated := testEval(tt.input)
+ evaluated := testEval(t, tt.input)
quote, ok := evaluated.(*object.Quote)
if !ok {
- t.Fatalf("expected *object.Quote. got=%T (%+v)",
- evaluated, evaluated)
+ t.Fatalf("expected *object.Quote. got=%T (%+v)", evaluated, evaluated)
}
if quote.Node == nil {
@@ -111,8 +108,7 @@ func TestQuoteUnquote(t *testing.T) {
}
if quote.Node.String() != tt.expected {
- t.Errorf("not equal. got=%q, want=%q",
- quote.Node.String(), tt.expected)
+ t.Errorf("not equal. got=%q, want=%q", quote.Node.String(), tt.expected)
}
}
}
diff --git a/go.mod b/go.mod
index 34c713d..058a786 100644
--- a/go.mod
+++ b/go.mod
@@ -1,3 +1,3 @@
module monkey
-go 1.12
+go 1.20
diff --git a/lexer/lexer.go b/lexer/lexer.go
index 12d4419..a0d4a5e 100644
--- a/lexer/lexer.go
+++ b/lexer/lexer.go
@@ -37,7 +37,7 @@ func (l *Lexer) NextToken() token.Token {
if l.peekChar() == '=' {
ch := l.ch
l.readChar()
- tok = token.Token{Type: token.NOT_EQ, Literal: string(ch) + string(l.ch)}
+ tok = token.Token{Type: token.NOTEQ, Literal: string(ch) + string(l.ch)}
} else {
tok = newToken(token.BANG, l.ch)
}
diff --git a/lexer/lexer_test.go b/lexer/lexer_test.go
index e692fea..5818dbe 100644
--- a/lexer/lexer_test.go
+++ b/lexer/lexer_test.go
@@ -107,7 +107,7 @@ macro(x, y) { x + y; };
{token.INTEGER, "10"},
{token.SEMICOLON, ";"},
{token.INTEGER, "10"},
- {token.NOT_EQ, "!="},
+ {token.NOTEQ, "!="},
{token.INTEGER, "9"},
{token.SEMICOLON, ";"},
{token.STRING, "foobar"},
@@ -145,13 +145,11 @@ macro(x, y) { x + y; };
tok := l.NextToken()
if tok.Type != tt.expectedType {
- t.Fatalf("tests[%d] - tokentype wrong. expected=%q, got=%q",
- i, tt.expectedType, tok.Type)
+ t.Fatalf("tests[%d] - tokentype wrong. expected=%q, got=%q", i, tt.expectedType, tok.Type)
}
if tok.Literal != tt.expectedLiteral {
- t.Fatalf("tests[%d] - literal wrong. expected=%q, got=%q",
- i, tt.expectedLiteral, tok.Literal)
+ t.Fatalf("tests[%d] - literal wrong. expected=%q, got=%q", i, tt.expectedLiteral, tok.Literal)
}
}
}
diff --git a/main.go b/main.go
index 21d17e7..0badd88 100644
--- a/main.go
+++ b/main.go
@@ -3,18 +3,12 @@ package main
import (
"fmt"
"os"
- "os/user"
"monkey/repl"
)
func main() {
- user, err := user.Current()
- if err != nil {
- panic(err)
- }
- fmt.Printf("Hello %s! This is the Monkey programming language!\n",
- user.Username)
- fmt.Printf("Feel free to type in commands\n")
+ fmt.Println("This is the Monkey programming language!")
+ fmt.Println("Feel free to type in commands")
repl.Start(os.Stdin, os.Stdout)
}
diff --git a/object/object.go b/object/object.go
index 2754bfb..f77b871 100644
--- a/object/object.go
+++ b/object/object.go
@@ -170,8 +170,7 @@ func (h *Hash) Inspect() string {
var pairs []string
for _, pair := range h.Pairs {
- pairs = append(pairs, fmt.Sprintf("%s: %s",
- pair.Key.Inspect(), pair.Value.Inspect()))
+ pairs = append(pairs, fmt.Sprintf("%s: %s", pair.Key.Inspect(), pair.Value.Inspect()))
}
out.WriteString("{")
diff --git a/object/objecttype_string.go b/object/objecttype_string.go
index 80d3ee6..39336a1 100644
--- a/object/objecttype_string.go
+++ b/object/objecttype_string.go
@@ -4,6 +4,24 @@ package object
import "strconv"
+func _() {
+ // An "invalid array index" compiler error signifies that the constant values have changed.
+ // Re-run the stringer command to generate them again.
+ var x [1]struct{}
+ _ = x[NULL-0]
+ _ = x[ERROR-1]
+ _ = x[INTEGER-2]
+ _ = x[BOOLEAN-3]
+ _ = x[STRING-4]
+ _ = x[RETURN_VALUE-5]
+ _ = x[FUNCTION-6]
+ _ = x[BUILTIN-7]
+ _ = x[ARRAY-8]
+ _ = x[HASH-9]
+ _ = x[QUOTE-10]
+ _ = x[MACRO-11]
+}
+
const _ObjectType_name = "NULLERRORINTEGERBOOLEANSTRINGRETURN_VALUEFUNCTIONBUILTINARRAYHASHQUOTEMACRO"
var _ObjectType_index = [...]uint8{0, 4, 9, 16, 23, 29, 41, 49, 56, 61, 65, 70, 75}
diff --git a/parser/parser.go b/parser/parser.go
index 910b1a1..b8c27d9 100644
--- a/parser/parser.go
+++ b/parser/parser.go
@@ -22,7 +22,7 @@ const (
var precedences = map[token.TokenType]int{
token.EQ: EQUALS,
- token.NOT_EQ: EQUALS,
+ token.NOTEQ: EQUALS,
token.LESS: LESSGREATER,
token.MORE: LESSGREATER,
token.PLUS: SUM,
@@ -40,7 +40,7 @@ type (
type Parser struct {
l *lexer.Lexer
- errors []string
+ errors []error
curToken token.Token
peekToken token.Token
@@ -74,7 +74,7 @@ func New(l *lexer.Lexer) *Parser {
token.SLASH: p.parseInfixExpression,
token.ASTERISK: p.parseInfixExpression,
token.EQ: p.parseInfixExpression,
- token.NOT_EQ: p.parseInfixExpression,
+ token.NOTEQ: p.parseInfixExpression,
token.LESS: p.parseInfixExpression,
token.MORE: p.parseInfixExpression,
token.LPAREN: p.parseCallExpression,
@@ -111,19 +111,18 @@ func (p *Parser) expectPeek(t token.TokenType) bool {
}
}
-func (p *Parser) Errors() []string {
+func (p *Parser) Errors() []error {
return p.errors
}
func (p *Parser) peekError(t token.TokenType) {
- msg := fmt.Sprintf("expected next token to be %s, got %s instead",
- t, p.peekToken.Type)
- p.errors = append(p.errors, msg)
+ err := fmt.Errorf("expected next token to be %s, got %s instead", t, p.peekToken.Type)
+ p.errors = append(p.errors, err)
}
func (p *Parser) noPrefixParseFnError(t token.TokenType) {
- msg := fmt.Sprintf("no prefix parse function for %s found", t)
- p.errors = append(p.errors, msg)
+ err := fmt.Errorf("no prefix parse function for %s found", t)
+ p.errors = append(p.errors, err)
}
func (p *Parser) ParseProgram() *ast.Program {
@@ -248,8 +247,8 @@ func (p *Parser) parseIntegerLiteral() ast.Expression {
value, err := strconv.ParseInt(p.curToken.Literal, 0, 64)
if err != nil {
- msg := fmt.Sprintf("could not parse %q as integer", p.curToken.Literal)
- p.errors = append(p.errors, msg)
+ err = fmt.Errorf("could not parse %q as integer: %w", p.curToken.Literal, err)
+ p.errors = append(p.errors, err)
return nil
}
diff --git a/parser/parser_test.go b/parser/parser_test.go
index df040ad..7b91214 100644
--- a/parser/parser_test.go
+++ b/parser/parser_test.go
@@ -12,7 +12,7 @@ func TestLetStatements(t *testing.T) {
tests := []struct {
input string
expectedIdentifier string
- expectedValue interface{}
+ expectedValue any
}{
{"let x = 5;", "x", 5},
{"let y = true;", "y", true},
@@ -26,8 +26,7 @@ func TestLetStatements(t *testing.T) {
checkParserErrors(t, p)
if len(program.Statements) != 1 {
- t.Fatalf("program.Statements does not contain 1 statements. got=%d",
- len(program.Statements))
+ t.Fatalf("program.Statements does not contain 1 statements. got=%d", len(program.Statements))
}
stmt := program.Statements[0]
@@ -45,7 +44,7 @@ func TestLetStatements(t *testing.T) {
func TestReturnStatements(t *testing.T) {
tests := []struct {
input string
- expectedValue interface{}
+ expectedValue any
}{
{"return 5;", 5},
{"return true;", true},
@@ -59,8 +58,7 @@ func TestReturnStatements(t *testing.T) {
checkParserErrors(t, p)
if len(program.Statements) != 1 {
- t.Fatalf("program.Statements does not contain 1 statements. got=%d",
- len(program.Statements))
+ t.Fatalf("program.Statements does not contain 1 statements. got=%d", len(program.Statements))
}
stmt := program.Statements[0]
@@ -69,8 +67,7 @@ func TestReturnStatements(t *testing.T) {
t.Fatalf("stmt not *ast.returnStatement. got=%T", stmt)
}
if returnStmt.TokenLiteral() != "return" {
- t.Fatalf("returnStmt.TokenLiteral not 'return', got %q",
- returnStmt.TokenLiteral())
+ t.Fatalf("returnStmt.TokenLiteral not 'return', got %q", returnStmt.TokenLiteral())
}
if testLiteralExpression(t, returnStmt.ReturnValue, tt.expectedValue) {
return
@@ -87,13 +84,11 @@ func TestIdentifierExpression(t *testing.T) {
checkParserErrors(t, p)
if len(program.Statements) != 1 {
- t.Fatalf("program has not enough statements. got=%d",
- len(program.Statements))
+ t.Fatalf("program has not enough statements. got=%d", len(program.Statements))
}
stmt, ok := program.Statements[0].(*ast.ExpressionStatement)
if !ok {
- t.Fatalf("program.Statements[0] is not ast.ExpressionStatement. got=%T",
- program.Statements[0])
+ t.Fatalf("program.Statements[0] is not ast.ExpressionStatement. got=%T", program.Statements[0])
}
ident, ok := stmt.Expression.(*ast.Identifier)
@@ -104,8 +99,7 @@ func TestIdentifierExpression(t *testing.T) {
t.Errorf("ident.Value not %s. got=%s", "foobar", ident.Value)
}
if ident.TokenLiteral() != "foobar" {
- t.Errorf("ident.TokenLiteral not %s. got=%s", "foobar",
- ident.TokenLiteral())
+ t.Errorf("ident.TokenLiteral not %s. got=%s", "foobar", ident.TokenLiteral())
}
}
@@ -118,13 +112,11 @@ func TestIntegerLiteralExpression(t *testing.T) {
checkParserErrors(t, p)
if len(program.Statements) != 1 {
- t.Fatalf("program has not enough statements. got=%d",
- len(program.Statements))
+ t.Fatalf("program has not enough statements. got=%d", len(program.Statements))
}
stmt, ok := program.Statements[0].(*ast.ExpressionStatement)
if !ok {
- t.Fatalf("program.Statements[0] is not ast.ExpressionStatement. got=%T",
- program.Statements[0])
+ t.Fatalf("program.Statements[0] is not ast.ExpressionStatement. got=%T", program.Statements[0])
}
literal, ok := stmt.Expression.(*ast.IntegerLiteral)
@@ -135,8 +127,7 @@ func TestIntegerLiteralExpression(t *testing.T) {
t.Errorf("literal.Value not %d. got=%d", 5, literal.Value)
}
if literal.TokenLiteral() != "5" {
- t.Errorf("literal.TokenLiteral not %s. got=%s", "5",
- literal.TokenLiteral())
+ t.Errorf("literal.TokenLiteral not %s. got=%s", "5", literal.TokenLiteral())
}
}
@@ -144,7 +135,7 @@ func TestParsingPrefixExpressions(t *testing.T) {
prefixTests := []struct {
input string
operator string
- value interface{}
+ value any
}{
{"!5;", "!", 5},
{"-15;", "-", 15},
@@ -161,14 +152,12 @@ func TestParsingPrefixExpressions(t *testing.T) {
checkParserErrors(t, p)
if len(program.Statements) != 1 {
- t.Fatalf("program.Statements does not contain %d statements. got=%d\n",
- 1, len(program.Statements))
+ t.Fatalf("program.Statements does not contain %d statements. got=%d", 1, len(program.Statements))
}
stmt, ok := program.Statements[0].(*ast.ExpressionStatement)
if !ok {
- t.Fatalf("program.Statements[0] is not ast.ExpressionStatement. got=%T",
- program.Statements[0])
+ t.Fatalf("program.Statements[0] is not ast.ExpressionStatement. got=%T", program.Statements[0])
}
exp, ok := stmt.Expression.(*ast.PrefixExpression)
@@ -176,8 +165,7 @@ func TestParsingPrefixExpressions(t *testing.T) {
t.Fatalf("stmt is not ast.PrefixExpression. got=%T", stmt.Expression)
}
if exp.Operator != tt.operator {
- t.Fatalf("exp.Operator is not '%s'. got=%s",
- tt.operator, exp.Operator)
+ t.Fatalf("exp.Operator is not '%s'. got=%s", tt.operator, exp.Operator)
}
if !testLiteralExpression(t, exp.Right, tt.value) {
return
@@ -188,9 +176,9 @@ func TestParsingPrefixExpressions(t *testing.T) {
func TestParsingInfixExpressions(t *testing.T) {
infixTests := []struct {
input string
- leftValue interface{}
+ leftValue any
operator string
- rightValue interface{}
+ rightValue any
}{
{"5 + 5;", 5, "+", 5},
{"5 - 5;", 5, "-", 5},
@@ -220,18 +208,15 @@ func TestParsingInfixExpressions(t *testing.T) {
checkParserErrors(t, p)
if len(program.Statements) != 1 {
- t.Fatalf("program.Statements does not contain %d statements. got=%d\n",
- 1, len(program.Statements))
+ t.Fatalf("program.Statements does not contain %d statements. got=%d", 1, len(program.Statements))
}
stmt, ok := program.Statements[0].(*ast.ExpressionStatement)
if !ok {
- t.Fatalf("program.Statements[0] is not ast.ExpressionStatement. got=%T",
- program.Statements[0])
+ t.Fatalf("program.Statements[0] is not ast.ExpressionStatement. got=%T", program.Statements[0])
}
- if !testInfixExpression(t, stmt.Expression, tt.leftValue,
- tt.operator, tt.rightValue) {
+ if !testInfixExpression(t, stmt.Expression, tt.leftValue, tt.operator, tt.rightValue) {
return
}
}
@@ -385,14 +370,12 @@ func TestBooleanExpression(t *testing.T) {
checkParserErrors(t, p)
if len(program.Statements) != 1 {
- t.Fatalf("program has not enough statements. got=%d",
- len(program.Statements))
+ t.Fatalf("program has not enough statements. got=%d", len(program.Statements))
}
stmt, ok := program.Statements[0].(*ast.ExpressionStatement)
if !ok {
- t.Fatalf("program.Statements[0] is not ast.ExpressionStatement. got=%T",
- program.Statements[0])
+ t.Fatalf("program.Statements[0] is not ast.ExpressionStatement. got=%T", program.Statements[0])
}
boolean, ok := stmt.Expression.(*ast.Boolean)
@@ -400,8 +383,7 @@ func TestBooleanExpression(t *testing.T) {
t.Fatalf("exp not *ast.Boolean. got=%T", stmt.Expression)
}
if boolean.Value != tt.expectedBoolean {
- t.Errorf("boolean.Value not %t. got=%t", tt.expectedBoolean,
- boolean.Value)
+ t.Errorf("boolean.Value not %t. got=%t", tt.expectedBoolean, boolean.Value)
}
}
}
@@ -415,20 +397,17 @@ func TestIfExpression(t *testing.T) {
checkParserErrors(t, p)
if len(program.Statements) != 1 {
- t.Fatalf("program.Body does not contain %d statements. got=%d\n",
- 1, len(program.Statements))
+ t.Fatalf("program.Body does not contain %d statements. got=%d", 1, len(program.Statements))
}
stmt, ok := program.Statements[0].(*ast.ExpressionStatement)
if !ok {
- t.Fatalf("program.Statements[0] is not ast.ExpressionStatement. got=%T",
- program.Statements[0])
+ t.Fatalf("program.Statements[0] is not ast.ExpressionStatement. got=%T", program.Statements[0])
}
exp, ok := stmt.Expression.(*ast.IfExpression)
if !ok {
- t.Fatalf("stmt.Expression is not ast.IfExpression. got=%T",
- stmt.Expression)
+ t.Fatalf("stmt.Expression is not ast.IfExpression. got=%T", stmt.Expression)
}
if !testInfixExpression(t, exp.Condition, "x", "<", "y") {
@@ -436,14 +415,12 @@ func TestIfExpression(t *testing.T) {
}
if len(exp.Consequence.Statements) != 1 {
- t.Errorf("consequence is not 1 statements. got=%d\n",
- len(exp.Consequence.Statements))
+ t.Errorf("consequence is not 1 statements. got=%d", len(exp.Consequence.Statements))
}
consequence, ok := exp.Consequence.Statements[0].(*ast.ExpressionStatement)
if !ok {
- t.Fatalf("Statements[0] is not ast.ExpressionStatement. got=%T",
- exp.Consequence.Statements[0])
+ t.Fatalf("Statements[0] is not ast.ExpressionStatement. got=%T", exp.Consequence.Statements[0])
}
if !testIdentifier(t, consequence.Expression, "x") {
@@ -464,14 +441,12 @@ func TestIfElseExpression(t *testing.T) {
checkParserErrors(t, p)
if len(program.Statements) != 1 {
- t.Fatalf("program.Body does not contain %d statements. got=%d\n",
- 1, len(program.Statements))
+ t.Fatalf("program.Body does not contain %d statements. got=%d", 1, len(program.Statements))
}
stmt, ok := program.Statements[0].(*ast.ExpressionStatement)
if !ok {
- t.Fatalf("program.Statements[0] is not ast.ExpressionStatement. got=%T",
- program.Statements[0])
+ t.Fatalf("program.Statements[0] is not ast.ExpressionStatement. got=%T", program.Statements[0])
}
exp, ok := stmt.Expression.(*ast.IfExpression)
@@ -484,14 +459,12 @@ func TestIfElseExpression(t *testing.T) {
}
if len(exp.Consequence.Statements) != 1 {
- t.Errorf("consequence is not 1 statements. got=%d\n",
- len(exp.Consequence.Statements))
+ t.Errorf("consequence is not 1 statements. got=%d", len(exp.Consequence.Statements))
}
consequence, ok := exp.Consequence.Statements[0].(*ast.ExpressionStatement)
if !ok {
- t.Fatalf("Statements[0] is not ast.ExpressionStatement. got=%T",
- exp.Consequence.Statements[0])
+ t.Fatalf("Statements[0] is not ast.ExpressionStatement. got=%T", exp.Consequence.Statements[0])
}
if !testIdentifier(t, consequence.Expression, "x") {
@@ -499,14 +472,12 @@ func TestIfElseExpression(t *testing.T) {
}
if len(exp.Alternative.Statements) != 1 {
- t.Errorf("exp.Alternative.Statements does not contain 1 statements. got=%d\n",
- len(exp.Alternative.Statements))
+ t.Errorf("exp.Alternative.Statements does not contain 1 statements. got=%d", len(exp.Alternative.Statements))
}
alternative, ok := exp.Alternative.Statements[0].(*ast.ExpressionStatement)
if !ok {
- t.Fatalf("Statements[0] is not ast.ExpressionStatement. got=%T",
- exp.Alternative.Statements[0])
+ t.Fatalf("Statements[0] is not ast.ExpressionStatement. got=%T", exp.Alternative.Statements[0])
}
if !testIdentifier(t, alternative.Expression, "y") {
@@ -523,39 +494,33 @@ func TestFunctionLiteralParsing(t *testing.T) {
checkParserErrors(t, p)
if len(program.Statements) != 1 {
- t.Fatalf("program.Body does not contain %d statements. got=%d\n",
- 1, len(program.Statements))
+ t.Fatalf("program.Body does not contain %d statements. got=%d", 1, len(program.Statements))
}
stmt, ok := program.Statements[0].(*ast.ExpressionStatement)
if !ok {
- t.Fatalf("program.Statements[0] is not ast.ExpressionStatement. got=%T",
- program.Statements[0])
+ t.Fatalf("program.Statements[0] is not ast.ExpressionStatement. got=%T", program.Statements[0])
}
function, ok := stmt.Expression.(*ast.FunctionLiteral)
if !ok {
- t.Fatalf("stmt.Expression is not ast.FunctionLiteral. got=%T",
- stmt.Expression)
+ t.Fatalf("stmt.Expression is not ast.FunctionLiteral. got=%T", stmt.Expression)
}
if len(function.Parameters) != 2 {
- t.Fatalf("function literal parameters wrong. want 2, got=%d\n",
- len(function.Parameters))
+ t.Fatalf("function literal parameters wrong. want 2, got=%d", len(function.Parameters))
}
testLiteralExpression(t, function.Parameters[0], "x")
testLiteralExpression(t, function.Parameters[1], "y")
if len(function.Body.Statements) != 1 {
- t.Fatalf("function.Body.Statements has not 1 statements. got=%d\n",
- len(function.Body.Statements))
+ t.Fatalf("function.Body.Statements has not 1 statements. got=%d", len(function.Body.Statements))
}
bodyStmt, ok := function.Body.Statements[0].(*ast.ExpressionStatement)
if !ok {
- t.Fatalf("function body stmt is not ast.ExpressionStatement. got=%T",
- function.Body.Statements[0])
+ t.Fatalf("function body stmt is not ast.ExpressionStatement. got=%T", function.Body.Statements[0])
}
testInfixExpression(t, bodyStmt.Expression, "x", "+", "y")
@@ -581,8 +546,7 @@ func TestFunctionParameterParsing(t *testing.T) {
function := stmt.Expression.(*ast.FunctionLiteral)
if len(function.Parameters) != len(tt.expectedParams) {
- t.Errorf("length parameters wrong. want %d, got=%d\n",
- len(tt.expectedParams), len(function.Parameters))
+ t.Errorf("length parameters wrong. want %d, got=%d", len(tt.expectedParams), len(function.Parameters))
}
for i, ident := range tt.expectedParams {
@@ -600,20 +564,17 @@ func TestCallExpressionParsing(t *testing.T) {
checkParserErrors(t, p)
if len(program.Statements) != 1 {
- t.Fatalf("program.Statements does not contain %d statements. got=%d\n",
- 1, len(program.Statements))
+ t.Fatalf("program.Statements does not contain %d statements. got=%d", 1, len(program.Statements))
}
stmt, ok := program.Statements[0].(*ast.ExpressionStatement)
if !ok {
- t.Fatalf("stmt is not ast.ExpressionStatement. got=%T",
- program.Statements[0])
+ t.Fatalf("stmt is not ast.ExpressionStatement. got=%T", program.Statements[0])
}
exp, ok := stmt.Expression.(*ast.CallExpression)
if !ok {
- t.Fatalf("stmt.Expression is not ast.CallExpression. got=%T",
- stmt.Expression)
+ t.Fatalf("stmt.Expression is not ast.CallExpression. got=%T", stmt.Expression)
}
if !testIdentifier(t, exp.Function, "add") {
@@ -661,8 +622,7 @@ func TestCallExpressionParameterParsing(t *testing.T) {
stmt := program.Statements[0].(*ast.ExpressionStatement)
exp, ok := stmt.Expression.(*ast.CallExpression)
if !ok {
- t.Fatalf("stmt.Expression is not ast.CallExpression. got=%T",
- stmt.Expression)
+ t.Fatalf("stmt.Expression is not ast.CallExpression. got=%T", stmt.Expression)
}
if !testIdentifier(t, exp.Function, tt.expectedIdent) {
@@ -670,14 +630,12 @@ func TestCallExpressionParameterParsing(t *testing.T) {
}
if len(exp.Arguments) != len(tt.expectedArgs) {
- t.Fatalf("wrong number of arguments. want=%d, got=%d",
- len(tt.expectedArgs), len(exp.Arguments))
+ t.Fatalf("wrong number of arguments. want=%d, got=%d", len(tt.expectedArgs), len(exp.Arguments))
}
for i, arg := range tt.expectedArgs {
if exp.Arguments[i].String() != arg {
- t.Errorf("argument %d wrong. want=%q, got=%q", i,
- arg, exp.Arguments[i].String())
+ t.Errorf("argument %d wrong. want=%q, got=%q", i, arg, exp.Arguments[i].String())
}
}
}
@@ -951,6 +909,7 @@ func TestParsingHashLiteralsWithExpressions(t *testing.T) {
}
func testLetStatement(t *testing.T, s ast.Statement, name string) bool {
+ t.Helper()
if s.TokenLiteral() != "let" {
t.Errorf("s.TokenLiteral not 'let'. got=%q", s.TokenLiteral())
return false
@@ -975,7 +934,8 @@ func testLetStatement(t *testing.T, s ast.Statement, name string) bool {
return true
}
-func testInfixExpression(t *testing.T, exp ast.Expression, left interface{}, operator string, right interface{}) bool {
+func testInfixExpression(t *testing.T, exp ast.Expression, left any, operator string, right any) bool {
+ t.Helper()
opExp, ok := exp.(*ast.InfixExpression)
if !ok {
t.Errorf("exp is not ast.OperatorExpression. got=%T(%s)", exp, exp)
@@ -998,7 +958,8 @@ func testInfixExpression(t *testing.T, exp ast.Expression, left interface{}, ope
return true
}
-func testLiteralExpression(t *testing.T, exp ast.Expression, expected interface{}) bool {
+func testLiteralExpression(t *testing.T, exp ast.Expression, expected any) bool {
+ t.Helper()
switch v := expected.(type) {
case int:
return testIntegerLiteral(t, exp, int64(v))
@@ -1014,6 +975,7 @@ func testLiteralExpression(t *testing.T, exp ast.Expression, expected interface{
}
func testIntegerLiteral(t *testing.T, il ast.Expression, value int64) bool {
+ t.Helper()
integ, ok := il.(*ast.IntegerLiteral)
if !ok {
t.Errorf("il not *ast.IntegerLiteral. got=%T", il)
@@ -1026,8 +988,7 @@ func testIntegerLiteral(t *testing.T, il ast.Expression, value int64) bool {
}
if integ.TokenLiteral() != fmt.Sprintf("%d", value) {
- t.Errorf("integ.TokenLiteral not %d. got=%s", value,
- integ.TokenLiteral())
+ t.Errorf("integ.TokenLiteral not %d. got=%s", value, integ.TokenLiteral())
return false
}
@@ -1035,6 +996,7 @@ func testIntegerLiteral(t *testing.T, il ast.Expression, value int64) bool {
}
func testIdentifier(t *testing.T, exp ast.Expression, value string) bool {
+ t.Helper()
ident, ok := exp.(*ast.Identifier)
if !ok {
t.Errorf("exp not *ast.Identifier. got=%T", exp)
@@ -1047,8 +1009,7 @@ func testIdentifier(t *testing.T, exp ast.Expression, value string) bool {
}
if ident.TokenLiteral() != value {
- t.Errorf("ident.TokenLiteral not %s. got=%s", value,
- ident.TokenLiteral())
+ t.Errorf("ident.TokenLiteral not %s. got=%s", value, ident.TokenLiteral())
return false
}
@@ -1056,6 +1017,7 @@ func testIdentifier(t *testing.T, exp ast.Expression, value string) bool {
}
func testBooleanLiteral(t *testing.T, exp ast.Expression, value bool) bool {
+ t.Helper()
bo, ok := exp.(*ast.Boolean)
if !ok {
t.Errorf("exp not *ast.Boolean. got=%T", exp)
@@ -1068,8 +1030,7 @@ func testBooleanLiteral(t *testing.T, exp ast.Expression, value bool) bool {
}
if bo.TokenLiteral() != fmt.Sprintf("%t", value) {
- t.Errorf("bo.TokenLiteral not %t. got=%s",
- value, bo.TokenLiteral())
+ t.Errorf("bo.TokenLiteral not %t. got=%s", value, bo.TokenLiteral())
return false
}
@@ -1098,39 +1059,33 @@ func TestMacroLiteralParsing(t *testing.T) {
checkParserErrors(t, p)
if len(program.Statements) != 1 {
- t.Fatalf("program.Statements does not contain %d statements. got=%d\n",
- 1, len(program.Statements))
+ t.Fatalf("program.Statements does not contain %d statements. got=%d", 1, len(program.Statements))
}
stmt, ok := program.Statements[0].(*ast.ExpressionStatement)
if !ok {
- t.Fatalf("statement is not ast.ExpressionStatement. got=%T",
- program.Statements[0])
+ t.Fatalf("statement is not ast.ExpressionStatement. got=%T", program.Statements[0])
}
macro, ok := stmt.Expression.(*ast.MacroLiteral)
if !ok {
- t.Fatalf("stmt.Expression is not ast.MacroLiteral. got=%T",
- stmt.Expression)
+ t.Fatalf("stmt.Expression is not ast.MacroLiteral. got=%T", stmt.Expression)
}
if len(macro.Parameters) != 2 {
- t.Fatalf("macro literal parameters wrong. want 2, got=%d\n",
- len(macro.Parameters))
+ t.Fatalf("macro literal parameters wrong. want 2, got=%d", len(macro.Parameters))
}
testLiteralExpression(t, macro.Parameters[0], "x")
testLiteralExpression(t, macro.Parameters[1], "y")
if len(macro.Body.Statements) != 1 {
- t.Fatalf("macro.Body.Statements has not 1 statements. got=%d\n",
- len(macro.Body.Statements))
+ t.Fatalf("macro.Body.Statements has not 1 statements. got=%d", len(macro.Body.Statements))
}
bodyStmt, ok := macro.Body.Statements[0].(*ast.ExpressionStatement)
if !ok {
- t.Fatalf("macro body stmt is not ast.ExpressionStatement. got=%T",
- macro.Body.Statements[0])
+ t.Fatalf("macro body stmt is not ast.ExpressionStatement. got=%T", macro.Body.Statements[0])
}
testInfixExpression(t, bodyStmt.Expression, "x", "+", "y")
diff --git a/parser/parser_tracing.go b/parser/parser_tracing.go
index bdffbd5..7f1f9e3 100644
--- a/parser/parser_tracing.go
+++ b/parser/parser_tracing.go
@@ -1,3 +1,4 @@
+//go:build ignore
// +build ignore
package parser
@@ -16,11 +17,11 @@ func identLevel() string {
}
func tracePrint(fs string) {
- fmt.Printf("%s%s\n", identLevel(), fs)
+ fmt.Println(identLevel(), fs)
}
-func incIdent() { traceLevel = traceLevel + 1 }
-func decIdent() { traceLevel = traceLevel - 1 }
+func incIdent() { traceLevel++ }
+func decIdent() { traceLevel-- }
func trace(msg string) string {
incIdent()
diff --git a/repl/face.txt b/repl/face.txt
new file mode 100644
index 0000000..14fdeb6
--- /dev/null
+++ b/repl/face.txt
@@ -0,0 +1,13 @@
+ __,__
+ .--. .-" "-. .--.
+ / .. \/ .-. .-. \/ .. \
+ | | '| / Y \ |' | |
+ | \ \ \ 0 | 0 / / / |
+ \ '- ,\.-"""""""-./, -' /
+ ''-' /_ ^ ^ _\ '-''
+ | \._ _./ |
+ \ \ '~' / /
+ '._ '-=-' _.'
+ '-----'
+
+Woops! We ran into some monkey business here!
diff --git a/repl/repl.go b/repl/repl.go
index 5537174..43a65f3 100644
--- a/repl/repl.go
+++ b/repl/repl.go
@@ -2,6 +2,7 @@ package repl
import (
"bufio"
+ _ "embed"
"fmt"
"io"
@@ -20,8 +21,7 @@ func Start(in io.Reader, out io.Writer) {
for {
fmt.Print(prompt)
- scanned := scanner.Scan()
- if !scanned {
+ if !scanner.Scan() {
return
}
@@ -46,24 +46,12 @@ func Start(in io.Reader, out io.Writer) {
}
}
-const MONKEY_FACE = ` __,__
- .--. .-" "-. .--.
- / .. \/ .-. .-. \/ .. \
- | | '| / Y \ |' | |
- | \ \ \ 0 | 0 / / / |
- \ '- ,\.-"""""""-./, -' /
- ''-' /_ ^ ^ _\ '-''
- | \._ _./ |
- \ \ '~' / /
- '._ '-=-' _.'
- '-----'
-`
+//go:embed face.txt
+var monkeyFace string
-func printParserErrors(out io.Writer, errors []string) {
- io.WriteString(out, MONKEY_FACE)
- io.WriteString(out, "Woops! We ran into some monkey business here!\n")
- io.WriteString(out, " parser errors:\n")
- for _, msg := range errors {
- io.WriteString(out, "\t"+msg+"\n")
+func printParserErrors(out io.Writer, errors []error) {
+ fmt.Fprintln(out, monkeyFace)
+ for _, err := range errors {
+ fmt.Fprintln(out, err)
}
}
diff --git a/token/token.go b/token/token.go
index ab33563..573483e 100644
--- a/token/token.go
+++ b/token/token.go
@@ -23,7 +23,7 @@ const (
LESS // "<"
MORE // ">"
EQ // "=="
- NOT_EQ // "!="
+ NOTEQ // "!="
// Delimiters
COMMA // ","
diff --git a/token/tokentype_string.go b/token/tokentype_string.go
index e7e554e..44b2c70 100644
--- a/token/tokentype_string.go
+++ b/token/tokentype_string.go
@@ -4,9 +4,47 @@ package token
import "strconv"
-const _TokenType_name = "ILLEGALEOFIDENTINTEGERSTRINGASSIGNPLUSMINUSBANGASTERISKSLASHLESSMOREEQNOT_EQCOMMASEMICOLONCOLONLPARENRPARENLBRACERBRACELBRACKETRBRACKETFUNCTIONLETTRUEFALSEIFELSERETURNMACRO"
+func _() {
+ // An "invalid array index" compiler error signifies that the constant values have changed.
+ // Re-run the stringer command to generate them again.
+ var x [1]struct{}
+ _ = x[ILLEGAL-0]
+ _ = x[EOF-1]
+ _ = x[IDENT-2]
+ _ = x[INTEGER-3]
+ _ = x[STRING-4]
+ _ = x[ASSIGN-5]
+ _ = x[PLUS-6]
+ _ = x[MINUS-7]
+ _ = x[BANG-8]
+ _ = x[ASTERISK-9]
+ _ = x[SLASH-10]
+ _ = x[LESS-11]
+ _ = x[MORE-12]
+ _ = x[EQ-13]
+ _ = x[NOTEQ-14]
+ _ = x[COMMA-15]
+ _ = x[SEMICOLON-16]
+ _ = x[COLON-17]
+ _ = x[LPAREN-18]
+ _ = x[RPAREN-19]
+ _ = x[LBRACE-20]
+ _ = x[RBRACE-21]
+ _ = x[LBRACKET-22]
+ _ = x[RBRACKET-23]
+ _ = x[FUNCTION-24]
+ _ = x[LET-25]
+ _ = x[TRUE-26]
+ _ = x[FALSE-27]
+ _ = x[IF-28]
+ _ = x[ELSE-29]
+ _ = x[RETURN-30]
+ _ = x[MACRO-31]
+}
+
+const _TokenType_name = "ILLEGALEOFIDENTINTEGERSTRINGASSIGNPLUSMINUSBANGASTERISKSLASHLESSMOREEQNOTEQCOMMASEMICOLONCOLONLPARENRPARENLBRACERBRACELBRACKETRBRACKETFUNCTIONLETTRUEFALSEIFELSERETURNMACRO"
-var _TokenType_index = [...]uint8{0, 7, 10, 15, 22, 28, 34, 38, 43, 47, 55, 60, 64, 68, 70, 76, 81, 90, 95, 101, 107, 113, 119, 127, 135, 143, 146, 150, 155, 157, 161, 167, 172}
+var _TokenType_index = [...]uint8{0, 7, 10, 15, 22, 28, 34, 38, 43, 47, 55, 60, 64, 68, 70, 75, 80, 89, 94, 100, 106, 112, 118, 126, 134, 142, 145, 149, 154, 156, 160, 166, 171}
func (i TokenType) String() string {
if i < 0 || i >= TokenType(len(_TokenType_index)-1) {