Skip to content

Commit

Permalink
Merge branch '2.4.x'
Browse files Browse the repository at this point in the history
  • Loading branch information
odino committed Mar 30, 2021
2 parents e8575e8 + 90d940f commit 4428eae
Show file tree
Hide file tree
Showing 11 changed files with 111 additions and 17 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
</p>

<p align="center">
<a href="https://github.com/abs-lang/abs"><img alt="GitHub branch checks state" src="https://img.shields.io/github/checks-status/abs-lang/abs/master"></a>
<a href="https://github.com/abs-lang/abs"><img alt="GitHub Workflow Status (branch)" src="https://img.shields.io/github/workflow/status/abs-lang/abs/tests/master"></a>
<a href="https://github.com/abs-lang/abs"><img alt="License" src="https://img.shields.io/github/license/abs-lang/abs.svg"></a>
<a href="https://github.com/abs-lang/abs"><img alt="Version" src="https://img.shields.io/github/release-pre/abs-lang/abs.svg"></a>
<img alt="undefined" src="https://img.shields.io/github/release-date/abs-lang/abs.svg?style=flat">
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.4.1
2.4.2
2 changes: 1 addition & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
</p>

<p align="center">
<a href="https://github.com/abs-lang/abs"><img alt="GitHub branch checks state" src="https://img.shields.io/github/checks-status/abs-lang/abs/master"></a>
<a href="https://github.com/abs-lang/abs"><img alt="GitHub Workflow Status (branch)" src="https://img.shields.io/github/workflow/status/abs-lang/abs/tests/master"></a>
<a href="https://github.com/abs-lang/abs"><img alt="License" src="https://img.shields.io/github/license/abs-lang/abs.svg"></a>
<a href="https://github.com/abs-lang/abs"><img alt="Version" src="https://img.shields.io/github/release-pre/abs-lang/abs.svg"></a>
<img href="https://github.com/abs-lang/abs/releases" alt="undefined" src="https://img.shields.io/github/release-date/abs-lang/abs.svg?style=flat">
Expand Down
Binary file modified docs/abs.wasm
100644 → 100755
Binary file not shown.
10 changes: 10 additions & 0 deletions evaluator/evaluator.go
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,8 @@ func evalPrefixExpression(tok token.Token, operator string, right object.Object)
return evalBangOperatorExpression(right)
case "-":
return evalMinusPrefixOperatorExpression(tok, right)
case "+":
return evalPlusPrefixOperatorExpression(tok, right)
case "~":
return evalTildePrefixOperatorExpression(tok, right)
default:
Expand Down Expand Up @@ -601,6 +603,14 @@ func evalMinusPrefixOperatorExpression(tok token.Token, right object.Object) obj
return &object.Number{Value: -value}
}

func evalPlusPrefixOperatorExpression(tok token.Token, right object.Object) object.Object {
if right.Type() != object.NUMBER_OBJ {
return newError(tok, "unknown operator: +%s", right.Type())
}

return right
}

func evalNumberInfixExpression(
tok token.Token, operator string,
left, right object.Object,
Expand Down
21 changes: 20 additions & 1 deletion evaluator/evaluator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,24 @@ func TestEvalNumberExpression(t *testing.T) {
{"a = 5; a **= 2; a", 25},
{"a = 5; a %= 3; a", 2},
{"a = 0; a += 1 + 1; a", 2},
{"2", 2},
{"-2", -2},
{"+2", 2},
{"+-2", -2},
{"+-+-+-2", -2},
{"2 + 1", 3},
{"2 +1", 3},
{"2 - 1", 1},
{"2 -1", 1},
{"+2", 2},
{"+2 +2", 4},
{" +2 + 2", 4},
{"+2 + 2", 4},
{"+ 2 + 2", 4},
{"-2 + 2", 0},
{"- 2 + 2", 0},
{"-2 +-2", -4},
{"x = 1; x+1", 2},
}

for _, tt := range tests {
Expand Down Expand Up @@ -296,7 +314,8 @@ func TestForExpressions(t *testing.T) {
{`x = 0; for k = 0; k < 11; k = k + 1 { if k < 10 { continue; }; x += k }; x`, 10},
{"a = 0; for x = 0; x < 10; x = x + 1 { a = a + 1}; a", 10},
{"a = 0; for x = 0; x < y; x = x + 1 { a = a + 1}; a", "identifier not found: y"},
{"a = 0; increment = f(x) {x+1}; for x = 0; x < 10; x = increment(x) { a = a + 1}; a", 10},
{"a = 0; increment = f(x) { x+1 }; for x = 0; x < 10; x = increment(x) { a = a + 1}; a", 10},
{"a = 0; decrement = f(x) { x-1 }; for x = 0; x > -10; x = decrement(x) { a = a + 1}; a", 10},
{`a = 0; for k = 0; k < 10; k = k + 1 { a = a + 1}; k`, "identifier not found: k"},
{`k = 100; for k = 0; k < 10; k = k { k = k + 1}; k`, 100},
{`k = 100; for k = y; k < 10; k = k { k = 9 }; k`, "identifier not found: y"},
Expand Down
59 changes: 59 additions & 0 deletions js/js.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package main

import (
"bytes"
"fmt"
"syscall/js"

"github.com/abs-lang/abs/evaluator"
"github.com/abs-lang/abs/lexer"
"github.com/abs-lang/abs/object"
"github.com/abs-lang/abs/parser"
)

// Version of the ABS interpreter
var Version = "dev"

// This function takes ABS code
// and evaluates it, using a buffer
// to store it's output.
// Once the code is evaluated, both
// the output and the return value of
// the script are returned to js in the
// form of {out, result}.
func runCode(this js.Value, i []js.Value) interface{} {
m := make(map[string]interface{})
var buf bytes.Buffer
// the first argument to our function
code := i[0].String()
env := object.NewEnvironment(&buf, "", Version)
lex := lexer.New(code)
p := parser.New(lex)

program := p.ParseProgram()

if len(p.Errors()) != 0 {
printParserErrors(p.Errors(), buf)
m["out"] = buf.String()
return js.ValueOf(m)
}

result := evaluator.BeginEval(program, env, lex)
m["out"] = buf.String()
m["result"] = result.Inspect()

return js.ValueOf(m)
}

func printParserErrors(errors []string, buf bytes.Buffer) {
fmt.Fprintf(&buf, "%s", " parser errors:\n")
for _, msg := range errors {
fmt.Fprintf(&buf, "%s", "\t"+msg+"\n")
}
}

func main() {
c := make(chan struct{}, 0)
js.Global().Set("abs_run_code", js.FuncOf(runCode))
<-c
}
7 changes: 0 additions & 7 deletions lexer/lexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,13 +107,6 @@ func (l *Lexer) NextToken() token.Token {
tok.Position = l.position
tok.Literal = "-="
l.readChar()
} else if isDigit(l.peekChar()) {
tok.Position = l.position
l.readChar()
literal, kind := l.readNumber()
tok.Type = kind
tok.Literal = "-" + literal
return tok
} else {
tok = l.newToken(token.MINUS)
}
Expand Down
3 changes: 2 additions & 1 deletion lexer/lexer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,8 @@ f hello(x, y) {
{token.ASSIGN, "="},
{token.NUMBER, "10"},
{token.SEMICOLON, ";"},
{token.NUMBER, "-10"},
{token.MINUS, "-"},
{token.NUMBER, "10"},
{token.SEMICOLON, ";"},
{token.MINUS, "-"},
{token.NUMBER, "10"},
Expand Down
20 changes: 16 additions & 4 deletions parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const (
INDEX // array[index]
QUESTION // some?.function() or some?.property
DOT // some.function() or some.property
HIGHEST // special preference for -x or +y
)

var precedences = map[token.TokenType]int{
Expand Down Expand Up @@ -97,6 +98,7 @@ func New(l *lexer.Lexer) *Parser {
p.registerPrefix(token.STRING, p.ParseStringLiteral)
p.registerPrefix(token.NULL, p.ParseNullLiteral)
p.registerPrefix(token.BANG, p.parsePrefixExpression)
p.registerPrefix(token.PLUS, p.parsePrefixExpression)
p.registerPrefix(token.MINUS, p.parsePrefixExpression)
p.registerPrefix(token.TILDE, p.parsePrefixExpression)
p.registerPrefix(token.TRUE, p.ParseBoolean)
Expand All @@ -115,10 +117,10 @@ func New(l *lexer.Lexer) *Parser {
p.registerPrefix(token.AT, p.parseDecorator)

p.infixParseFns = make(map[token.TokenType]infixParseFn)
p.registerInfix(token.QUESTION, p.parseQuestionExpression)
p.registerInfix(token.DOT, p.parseDottedExpression)
p.registerInfix(token.PLUS, p.parseInfixExpression)
p.registerInfix(token.MINUS, p.parseInfixExpression)
p.registerInfix(token.QUESTION, p.parseQuestionExpression)
p.registerInfix(token.DOT, p.parseDottedExpression)
p.registerInfix(token.SLASH, p.parseInfixExpression)
p.registerInfix(token.EXPONENT, p.parseInfixExpression)
p.registerInfix(token.MODULO, p.parseInfixExpression)
Expand Down Expand Up @@ -380,6 +382,7 @@ func (p *Parser) parseExpressionStatement() *ast.ExpressionStatement {

func (p *Parser) parseExpression(precedence int) ast.Expression {
prefix := p.prefixParseFns[p.curToken.Type]

if prefix == nil {
p.noPrefixParseFnError(p.curToken)
return nil
Expand Down Expand Up @@ -465,9 +468,18 @@ func (p *Parser) parsePrefixExpression() ast.Expression {
Token: p.curToken,
Operator: p.curToken.Literal,
}

precedence := PREFIX

// When +- are used as prefixes, we want them to have
// the highest priority, so that -5.clamp(4, 5) is read
// as (-5).clamp(4, 5) = 4 instead of
// -(5.clamp(4,5)) = -5
if p.curTokenIs(token.PLUS) || p.curTokenIs(token.MINUS) {
precedence = HIGHEST
}
p.nextToken()
expression.Right = p.parseExpression(PREFIX)

expression.Right = p.parseExpression(precedence)

return expression
}
Expand Down
2 changes: 1 addition & 1 deletion parser/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ func TestOperatorPrecedenceParsing(t *testing.T) {
},
{
"3 + 4; -5 * 5",
"(3 + 4)(-5 * 5)",
"(3 + 4)((-5) * 5)",
},
{
"3 + 4; - 5 * 5",
Expand Down

0 comments on commit 4428eae

Please sign in to comment.