diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/anglais.iml b/.idea/anglais.iml
new file mode 100644
index 0000000..11646b4
--- /dev/null
+++ b/.idea/anglais.iml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..6c7658f
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..36d0426
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/core/compiler.go b/core/compiler.go
index 928eff0..617871e 100644
--- a/core/compiler.go
+++ b/core/compiler.go
@@ -3,7 +3,6 @@ package core
import (
"errors"
"fmt"
- "slices"
"strings"
)
@@ -117,7 +116,8 @@ func (e CompilerError) Format() string {
b.WriteString("\nsource trace:")
// print import stack trace
- for i, p := range slices.Backward(e.Trace) {
+ for i := len(e.Trace) - 1; i >= 0; i-- {
+ p := e.Trace[i]
b.WriteString(fmt.Sprintf("\n[%d] %s", i, p))
}
@@ -180,20 +180,20 @@ func (c *Compiler) Compile(p *Program) (TypeSignature, error) {
}
func EscapeString(in string) string {
- var out strings.Builder
+ out := ""
escaped := false
for _, ch := range in {
if escaped {
switch ch {
case 'n':
- out.WriteRune('\n')
+ out += "\n"
case 't':
- out.WriteRune('\t')
+ out += "\t"
case 'r':
- out.WriteRune('\r')
+ out += "\r"
default:
- out.WriteString(string(ch))
+ out += string(ch)
}
escaped = false
continue
@@ -203,11 +203,11 @@ func EscapeString(in string) string {
case '\\':
escaped = true
default:
- out.WriteString(string(ch))
+ out += string(ch)
}
}
- return out.String()
+ return out
}
func (c *Compiler) resolveType(value TypeSignature) TypeSignature {
@@ -265,30 +265,6 @@ func (c *Compiler) compile(tree Node) (TypeSignature, error) {
return &TupleSignature{contents}, nil
- case RecordNodeType:
- n := tree.(*RecordNode)
-
- c.add(InstructionNewRecord)
-
- contents := map[string]TypeSignature{}
- for k, v := range n.entries {
- t, err := c.compile(v)
- if err != nil {
- return nil, err
- }
-
- c.add(InstructionSetRecordItem)
- c.addConstant(&StringValue{
- k,
- })
-
- contents[k] = t
- }
-
- return &RecordSignature{
- contents,
- }, nil
-
case ListNodeType:
l := tree.(*ListNode)
@@ -968,8 +944,8 @@ func (c *Compiler) compileAssignFromStack(to Node, sig TypeSignature, declare bo
c.add(InstructionDestructureTuple)
// iterate from top to bottom
- for i, v := range slices.Backward(t.items) {
- _, err := c.compileAssignFromStack(v, tsig.Contents[i], declare)
+ for i := len(t.items) - 1; i >= 0; i-- {
+ _, err := c.compileAssignFromStack(t.items[i], tsig.Contents[i], declare)
if err != nil {
return nil, err
}
@@ -977,41 +953,6 @@ func (c *Compiler) compileAssignFromStack(to Node, sig TypeSignature, declare bo
}
return sig, nil
- case IndexNodeType:
- if declare {
- return nil, c.error(fmt.Sprintf("cannot declare an indexed item"), to)
- }
-
- n := to.(*IndexNode)
-
- ssig, err := c.compile(n.source)
- if err != nil {
- return nil, err
- }
-
- isig, err := c.compile(n.index)
- if err != nil {
- return nil, err
- }
-
- if isig.Type() != TypeInteger {
- return nil, c.error(fmt.Sprintf("cannot index into list with non-integer (%s)", isig), n.index)
- }
-
- switch ssig.Type() {
- case TypeList:
- lsig := ssig.(*ListSignature)
- if !c.typeMatches(sig, lsig.Contents) {
- return nil, c.error(fmt.Sprintf("cannot assign value of type %s to list with items of type %s", sig, lsig.Contents), to)
- }
-
- c.add(InstructionSetIndexList)
- default:
- return nil, c.error(fmt.Sprintf("cannot set index of %s", ssig.Type()), n.source)
- }
-
- return sig, nil
-
default:
return nil, c.error(fmt.Sprintf("cannot assign to %s", to.Type()), to)
}
@@ -1255,13 +1196,6 @@ func (c *Compiler) getPropertySignature(source TypeSignature, property string) (
return &CompositeSignature{
at, bt,
}, nil
- case TypeRecord:
- prop, ok := sig.(*RecordSignature).Entries[property]
- if !ok {
- return nil, errors.New(fmt.Sprintf("cannot record has no property \"%s\"", property))
- }
-
- return prop, nil
default:
}
diff --git a/core/lexer.go b/core/lexer.go
index 1701479..ba504b8 100644
--- a/core/lexer.go
+++ b/core/lexer.go
@@ -7,7 +7,7 @@ import (
)
type Token struct {
- Kind TokenKind
+ Type TokenKind
Start Pos
End Pos
Line Pos
@@ -19,7 +19,7 @@ func (t Token) Bounds() (Pos, Pos) {
}
func (t Token) String() string {
- return fmt.Sprintf("token %s, '%s' %d -> %d, line %d", t.Kind.String(), t.Lexeme, t.Start, t.End, t.Line)
+ return fmt.Sprintf("token %s, '%s' %d -> %d, line %d", t.Type.String(), t.Lexeme, t.Start, t.End, t.Line)
}
type TokenKind uint64
@@ -185,8 +185,6 @@ func (t TokenKind) String() string {
return "for"
case TokenIn:
return "in"
- case TokenPercent:
- return "percent"
}
panic("UNDEFINED TOKENTYPE STRING CONVERSION")
@@ -417,7 +415,7 @@ func (l *Lexer) NextToken() (Token, error) {
func NewToken(t TokenKind, start Pos, end Pos, line Pos, lexeme string) Token {
return Token{
- Kind: t,
+ Type: t,
Start: start,
End: end,
Line: line,
@@ -432,7 +430,7 @@ func (l *Lexer) Tokenize() ([]Token, error) {
for ; err == nil; tok, err = l.NextToken() {
tokens = append(tokens, tok)
- if tok.Kind == TokenEOF {
+ if tok.Type == TokenEOF {
break
}
}
diff --git a/core/lexer_test.go b/core/lexer_test.go
index a20a0c1..c8158b3 100644
--- a/core/lexer_test.go
+++ b/core/lexer_test.go
@@ -148,8 +148,8 @@ func TestLexer_NextToken(t *testing.T) {
continue
}
- if tok.Kind != expectedType {
- t.Errorf("Expected token type '%s' but got '%s'", expectedType, tok.Kind)
+ if tok.Type != expectedType {
+ t.Errorf("Expected token type '%s' but got '%s'", expectedType, tok.Type)
} else {
t.Logf("Got expected token type '%s'", expectedType)
}
@@ -193,7 +193,7 @@ func TestLexer_NextTokenErrors(t *testing.T) {
lex := NewLexer(code)
tok, err := lex.NextToken()
- for err == nil && tok.Kind != TokenEOF {
+ for err == nil && tok.Type != TokenEOF {
tok, err = lex.NextToken()
}
@@ -220,7 +220,7 @@ func BenchmarkLexer_NextToken(b *testing.B) {
lex := NewLexer(tc.source)
tok, err := lex.NextToken()
- for err == nil && tok.Kind != TokenEOF {
+ for err == nil && tok.Type != TokenEOF {
tok, err = lex.NextToken()
}
}
diff --git a/core/nodes.go b/core/nodes.go
index 0a04c44..056b206 100644
--- a/core/nodes.go
+++ b/core/nodes.go
@@ -29,7 +29,6 @@ const (
NilNodeType
ListNodeType
TupleNodeType
- RecordNodeType
BinaryNodeType
UnaryNodeType
BlockNodeType
@@ -94,12 +93,6 @@ func (n NodeType) String() string {
return "Alias"
case IndexNodeType:
return "Index"
- case RecordNodeType:
- return "Record"
- case ForNodeType:
- return "For"
- case IncludeNodeType:
- return "Include"
}
return "Invalid Node Type"
}
@@ -244,36 +237,6 @@ func (n TupleNode) Bounds() (Pos, Pos) {
return n.start, n.end
}
-type RecordNode struct {
- entries map[string]Node
-
- start Pos
- end Pos
-}
-
-func (n RecordNode) Type() NodeType {
- return RecordNodeType
-}
-
-func (n RecordNode) String() string {
- sb := strings.Builder{}
-
- sb.WriteString("(")
- for name, item := range n.entries {
- sb.WriteString(name)
- sb.WriteString(": ")
- sb.WriteString(item.String())
- sb.WriteString(",")
- }
- sb.WriteString(")")
-
- return sb.String()
-}
-
-func (n RecordNode) Bounds() (Pos, Pos) {
- return n.start, n.end
-}
-
type AccessNode struct {
source Node
property *Token
@@ -306,8 +269,6 @@ func (n BinaryOperation) String() string {
return "multiply"
case BinaryDivision:
return "divide"
- case BinaryModulo:
- return "modulo"
case BinaryEquality:
return "equality"
case BinaryInequality:
@@ -538,7 +499,7 @@ func (n ConditionalNode) String() string {
return fmt.Sprintf("if %s then %s", n.condition.String(), n.do.String())
}
- return fmt.Sprintf("if %s then %s otherwise %s", n.condition.String(), n.do.String(), n.otherwise.String())
+ return fmt.Sprintf("if %s then %s otheriwise %s", n.condition.String(), n.do.String(), n.otherwise.String())
}
func (n ConditionalNode) Bounds() (Pos, Pos) {
diff --git a/core/optimizer.go b/core/optimizer.go
new file mode 100644
index 0000000..fe08fec
--- /dev/null
+++ b/core/optimizer.go
@@ -0,0 +1,250 @@
+package core
+
+import (
+ "fmt"
+ "math/big"
+)
+
+type TreeOptimizer struct{}
+
+func (t *TreeOptimizer) Optimize(node *Node) {
+ panic("unimplemented")
+}
+
+func (t *TreeOptimizer) error(message string, causer Bounded) error {
+ panic("unimplemented")
+}
+
+// isTreeConstant check if a node tree is constant (predictable)
+func (t *TreeOptimizer) isTreeConstant(tree Node) bool {
+ switch tree.Type() {
+ case StringNodeType, FloatNodeType, IntegerNodeType, BooleanNodeType, NilNodeType:
+ return true
+ case ListNodeType:
+ for _, item := range tree.(*ListNode).items {
+ if !t.isTreeConstant(item) {
+ return false
+ }
+ }
+
+ return true
+ case UnaryNodeType:
+ return t.isTreeConstant(tree.(*UnaryNode).value)
+ case BinaryNodeType:
+ return t.isTreeConstant(tree.(*BinaryNode).Left) && t.isTreeConstant(tree.(*BinaryNode).Right)
+ case InvokeNodeType:
+ for _, arg := range tree.(*InvokeNode).args {
+ if !t.isTreeConstant(arg) {
+ return false
+ }
+ }
+ return t.isTreeConstant(tree.(*InvokeNode).source)
+ case BlockNodeType, ConditionalNodeType, LoopNodeType, AssignNodeType, FunctionNodeType,
+ ReturnNodeType, AccessNodeType, BreakpointNodeType, ReferenceNodeType:
+ return false
+ default:
+ panic(fmt.Sprintf("unexpected node %s", tree))
+ }
+}
+
+func (t *TreeOptimizer) compute(tree Node) (Value, error) {
+ switch n := tree.(type) {
+ case *StringNode:
+ return &StringValue{
+ EscapeString(n.value),
+ }, nil
+
+ case *FloatNode:
+ return &FloatValue{
+ n.value,
+ }, nil
+
+ case *IntegerNode:
+ return &IntegerValue{
+ n.value,
+ }, nil
+
+ case *BooleanNode:
+ return &BoolValue{
+ n.Boolean,
+ }, nil
+
+ case *NilNode:
+ return &NilValue{}, nil
+
+ case *ListNode:
+ items := make([]Value, len(n.items))
+ var err error
+ for i, item := range n.items {
+ items[i], err = t.compute(item)
+
+ if err != nil {
+ return nil, err
+ }
+ }
+ return &ListValue{
+ items,
+ }, nil
+
+ case *BinaryNode:
+ return t.computeBinary(n)
+
+ case *UnaryNode:
+ v, err := t.compute(n.value)
+ if err != nil {
+ return nil, err
+ }
+
+ switch n.UnaryOperation {
+ case UnaryNegate:
+ if v.Type() == FloatValueType {
+ return &FloatValue{
+ -v.(*FloatValue).Number,
+ }, nil
+ } else if v.Type() == IntegerValueType {
+ return &IntegerValue{
+ new(big.Int).Neg(v.(*IntegerValue).Number),
+ }, nil
+ }
+
+ return nil, t.error(fmt.Sprintf("cannot negate %s value (not a number)", v.Type()), n)
+ case UnaryNot:
+ if v.Type() != BoolValueType {
+ return nil, t.error(fmt.Sprintf("cannot invert %s value (not a boolean)", v.Type()), n)
+ }
+
+ return &BoolValue{
+ !v.(*BoolValue).Boolean,
+ }, nil
+ }
+
+ return nil, t.error(fmt.Sprintf("unimplemented unary %s", v.Type()), n)
+
+ case *InvokeNode:
+ source, err := t.compute(n.source)
+ if err != nil {
+ return nil, err
+ }
+
+ f, ok := source.(*BuiltinFunctionValue)
+ if !ok {
+ return nil, nil
+ }
+
+ if !f.Constant {
+ return nil, nil
+ }
+
+ args := make([]Value, len(f.Signature.In))
+ for i, arg := range n.args {
+ args[i], err = t.compute(arg)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ return f.F(nil, nil, args)
+
+ default:
+ panic(fmt.Sprintf("unexpected node %s, %T", tree.String(), tree))
+ }
+}
+
+func (t *TreeOptimizer) computeBinary(n *BinaryNode) (Value, error) {
+ l, err := t.compute(n.Left)
+ if err != nil {
+ return nil, err
+ }
+ r, err := t.compute(n.Right)
+ if err != nil {
+ return nil, err
+ }
+
+ if l.Type() != r.Type() {
+ return nil, t.error(fmt.Sprintf("cannot %s different types %s and %s", n.BinaryOperation, l.Type(), r.Type()), n)
+ }
+
+ // perform type check
+ switch n.BinaryOperation {
+ case BinarySubtraction, BinaryMultiplication, BinaryDivision, BinaryLess, BinaryGreater, BinaryLessEqual, BinaryGreaterEqual:
+ if l.Type() != FloatValueType && l.Type() != IntegerValueType {
+ return nil, t.error(fmt.Sprintf("cannot %s values of non-number type %s", n.BinaryOperation, l.Type()), n)
+ }
+ case BinaryBooleanAnd, BinaryBooleanOr:
+ if l.Type() != BoolValueType {
+ return nil, t.error(fmt.Sprintf("cannot %s values of non-boolean type %s", n.BinaryOperation, l.Type()), n)
+ }
+ case BinaryEquality, BinaryInequality:
+ // can compare all types with themselves
+ default:
+ }
+
+ var v interface{}
+ switch n.BinaryOperation {
+ case BinaryAddition:
+ switch l.Type() {
+ case FloatValueType:
+ v = l.(*FloatValue).Number + r.(*FloatValue).Number
+ case StringValueType:
+ v = l.(*StringValue).Text + r.(*StringValue).Text
+ case ListValueType:
+ v = append(l.(*ListValue).Items, r.(*ListValue).Items...)
+ case IntegerValueType:
+ v = new(big.Int).Add(l.(*IntegerValue).Number, r.(*IntegerValue).Number)
+ default:
+ return nil, t.error(fmt.Sprintf("cannot add values of type %s", l.Type()), n)
+ }
+ case BinarySubtraction:
+ if l.Type() == FloatValueType {
+ v = l.(*FloatValue).Number - r.(*FloatValue).Number
+ } else {
+ v = new(big.Int).Sub(l.(*IntegerValue).Number, r.(*IntegerValue).Number)
+ }
+ case BinaryMultiplication:
+ if l.Type() == FloatValueType {
+ v = l.(*FloatValue).Number * r.(*FloatValue).Number
+ } else {
+ v = new(big.Int).Mul(l.(*IntegerValue).Number, r.(*IntegerValue).Number)
+ }
+ case BinaryDivision:
+ if l.Type() == FloatValueType {
+ v = l.(*FloatValue).Number / r.(*FloatValue).Number
+ } else {
+ v = new(big.Int).Div(l.(*IntegerValue).Number, r.(*IntegerValue).Number)
+ }
+ case BinaryBooleanAnd:
+ v = l.(*BoolValue).Boolean && r.(*BoolValue).Boolean
+ case BinaryBooleanOr:
+ v = l.(*BoolValue).Boolean || r.(*BoolValue).Boolean
+ case BinaryEquality:
+ v = l.Equals(r)
+ case BinaryInequality:
+ v = !l.Equals(r)
+ case BinaryLess:
+ if l.Type() == FloatValueType {
+ v = l.(*FloatValue).Number < r.(*FloatValue).Number
+ } else {
+ v = l.(*IntegerValue).Number.Cmp(r.(*IntegerValue).Number) == -1
+ }
+ case BinaryGreater:
+ if l.Type() == FloatValueType {
+ v = l.(*FloatValue).Number > r.(*FloatValue).Number
+ } else {
+ v = l.(*IntegerValue).Number.Cmp(r.(*IntegerValue).Number) == 1
+ }
+ case BinaryLessEqual:
+ if l.Type() == FloatValueType {
+ v = l.(*FloatValue).Number <= r.(*FloatValue).Number
+ } else {
+ v = l.(*IntegerValue).Number.Cmp(r.(*IntegerValue).Number) != 1
+ }
+ case BinaryGreaterEqual:
+ if l.Type() == FloatValueType {
+ v = l.(*FloatValue).Number >= r.(*FloatValue).Number
+ } else {
+ v = l.(*IntegerValue).Number.Cmp(r.(*IntegerValue).Number) != 1
+ }
+ }
+
+ return GoToValue(v), nil
+}
diff --git a/core/parser.go b/core/parser.go
index 7383f51..6462b7a 100644
--- a/core/parser.go
+++ b/core/parser.go
@@ -5,7 +5,6 @@ import (
"fmt"
"log"
"math/big"
- "slices"
"strconv"
"strings"
)
@@ -69,21 +68,17 @@ func (p ParsingError) Format() string {
b.WriteRune('\n')
b.WriteRune('\n')
- for i, v := range slices.Backward(p.Trace) {
- b.WriteString(fmt.Sprintf("[%d] %s\n", i, v))
+ for i := len(p.Trace) - 1; i >= 0; i-- {
+ b.WriteString(fmt.Sprintf("[%d] %s\n", i, p.Trace[i]))
}
return b.String()
}
type Parser struct {
- source string
- trace []string
- tokens []Token
- state ParserState
-}
-
-type ParserState struct {
+ source string
+ trace []string
+ tokens []Token
prev *Token
curr *Token
pos Pos
@@ -95,9 +90,7 @@ func NewParser(source string, trace []string, tokens []Token) *Parser {
source: source,
trace: trace,
tokens: tokens,
- state: ParserState{
- pos: 0,
- },
+ pos: 0,
}
}
@@ -123,11 +116,11 @@ func (p *Parser) Parse(path string) (*Program, error) {
// initialize current
p.advance()
- for int(p.state.pos) < len(p.tokens) && p.state.curr.Kind != TokenEOF {
+ for int(p.pos) < len(p.tokens) && p.curr.Type != TokenEOF {
for p.accept(TokenNewLine) {
}
- if p.state.curr.Kind == TokenEOF {
+ if p.curr.Type == TokenEOF {
break
}
@@ -146,25 +139,25 @@ func (p *Parser) Parse(path string) (*Program, error) {
&BlockNode{
statements,
0,
- p.state.curr.End,
+ p.curr.End,
},
path,
}, nil
}
func (p *Parser) accept(tokenType TokenKind) bool {
- if p.state.curr == nil {
+ if p.curr == nil {
log.Fatal("unexpected current token nil")
return false
}
- if p.state.ignoreNewLine && tokenType != TokenNewLine {
- for p.state.curr.Kind == TokenNewLine {
+ if p.ignoreNewLine && tokenType != TokenNewLine {
+ for p.curr.Type == TokenNewLine {
p.advance()
}
}
- if (*p.state.curr).Kind == tokenType {
+ if (*p.curr).Type == tokenType {
p.advance()
return true
}
@@ -172,52 +165,46 @@ func (p *Parser) accept(tokenType TokenKind) bool {
return false
}
-func (p *Parser) getState() ParserState {
- return p.state
-}
+func (p *Parser) acceptAll(tokenTypes ...TokenKind) bool {
+ if int(p.pos)+len(tokenTypes) > len(p.tokens) {
+ return false
+ }
-func (p *Parser) restoreState(state ParserState) {
- p.state = state
-}
-
-func (p *Parser) acceptSeq(tokenTypes ...TokenKind) bool {
- state := p.getState()
-
- for _, t := range tokenTypes {
- if !p.accept(t) {
- p.restoreState(state)
+ for i, tokenType := range tokenTypes {
+ if p.tokens[int(p.pos)+i].Type != tokenType {
return false
}
}
+ p.pos += Pos(len(tokenTypes))
return true
}
func (p *Parser) expect(tokenType TokenKind, reason string) error {
if !p.accept(tokenType) {
- return p.error(fmt.Sprintf("Expected token %s, got %s; %s", tokenType, p.state.curr.Kind, reason), p.state.curr)
+ return p.error(fmt.Sprintf("Expected token %s, got %s; %s", tokenType, p.curr.Type, reason), p.curr)
}
return nil
}
func (p *Parser) peek() (Token, error) {
- if p.state.pos >= Pos(len(p.tokens)) {
+ if p.pos >= Pos(len(p.tokens)) {
return Token{}, errors.New("cannot peek beyond tokens")
}
- return p.tokens[p.state.pos], nil
+ return p.tokens[p.pos], nil
}
func (p *Parser) advance() {
- p.state.prev = p.state.curr
+ p.prev = p.curr
- if p.state.pos < Pos(len(p.tokens)) {
- p.state.curr = &p.tokens[p.state.pos]
+ if p.pos < Pos(len(p.tokens)) {
+ p.curr = &p.tokens[p.pos]
} else {
- p.state.curr = nil
+ p.curr = nil
}
- p.state.pos++
+ p.pos++
}
func (p *Parser) error(error string, causer *Token) error {
@@ -237,10 +224,10 @@ func (p *Parser) expression(mustBeBlock bool) (Node, error) {
}
}
- oldIgnoreNewline := p.state.ignoreNewLine
- p.state.ignoreNewLine = false
+ oldIgnoreNewline := p.ignoreNewLine
+ p.ignoreNewLine = false
- start := p.state.prev.Start
+ start := p.prev.Start
var statements []Node
for !p.accept(TokenCloseBrace) {
@@ -264,22 +251,22 @@ func (p *Parser) expression(mustBeBlock bool) (Node, error) {
}
}
- p.state.ignoreNewLine = oldIgnoreNewline
+ p.ignoreNewLine = oldIgnoreNewline
- return &BlockNode{statements, start, p.state.prev.End}, nil
+ return &BlockNode{statements, start, p.prev.End}, nil
}
- t := p.state.curr
- switch t.Kind {
+ t := p.curr
+ switch t.Type {
case TokenType:
p.advance()
- start := p.state.prev.Start
+ start := p.prev.Start
if err := p.expect(TokenName, "types must have a name"); err != nil {
return nil, err
}
- name := p.state.prev
+ name := p.prev
if err := p.expect(TokenAssign, "type aliases must be defined with an assign"); err != nil {
return nil, err
@@ -295,7 +282,7 @@ func (p *Parser) expression(mustBeBlock bool) (Node, error) {
sig,
start,
- p.state.prev.End,
+ p.prev.End,
}, nil
case TokenIf:
@@ -313,7 +300,7 @@ func (p *Parser) expression(mustBeBlock bool) (Node, error) {
var otherwise Node
if p.accept(TokenElse) {
- otherwise, err = p.expression(p.state.curr.Kind != TokenIf)
+ otherwise, err = p.expression(p.curr.Type != TokenIf)
if err != nil {
return nil, err
}
@@ -329,7 +316,7 @@ func (p *Parser) expression(mustBeBlock bool) (Node, error) {
case TokenReturn:
p.advance()
- start := p.state.prev.Start
+ start := p.prev.Start
v, err := p.expression(false)
if err != nil {
@@ -339,12 +326,12 @@ func (p *Parser) expression(mustBeBlock bool) (Node, error) {
return &ReturnNode{
v,
start,
- p.state.prev.End,
+ p.prev.End,
}, nil
case TokenWhile:
p.advance()
- start := p.state.prev.Start
+ start := p.prev.Start
cond, err := p.expression(false)
if err != nil {
@@ -360,12 +347,12 @@ func (p *Parser) expression(mustBeBlock bool) (Node, error) {
cond,
logic,
start,
- p.state.prev.End,
+ p.prev.End,
}, nil
case TokenFor:
p.advance()
- start := p.state.prev.Start
+ start := p.prev.Start
counter, err := p.expression(false)
if err != nil {
@@ -392,12 +379,12 @@ func (p *Parser) expression(mustBeBlock bool) (Node, error) {
logic,
start,
- p.state.prev.End,
+ p.prev.End,
}, nil
case TokenInclude:
p.advance()
- start := p.state.prev.Start
+ start := p.prev.Start
if err := p.expect(TokenString, "import requires a path/name to include"); err != nil {
return nil, err
@@ -405,13 +392,13 @@ func (p *Parser) expression(mustBeBlock bool) (Node, error) {
return &IncludeNode{
&StringNode{
- p.state.prev.Lexeme[1 : len(p.state.prev.Lexeme)-1],
- p.state.prev.Lexeme,
- p.state.prev.Start,
- p.state.prev.End,
+ p.prev.Lexeme[1 : len(p.prev.Lexeme)-1],
+ p.prev.Lexeme,
+ p.prev.Start,
+ p.prev.End,
},
start,
- p.state.prev.End,
+ p.prev.End,
}, nil
default:
@@ -421,7 +408,7 @@ func (p *Parser) expression(mustBeBlock bool) (Node, error) {
}
if p.accept(TokenDeclare) || p.accept(TokenAssign) {
- isDeclaration := p.state.prev.Kind == TokenDeclare
+ isDeclaration := p.prev.Type == TokenDeclare
// possibly assign tuples; not implemented yet
v, err := p.expression(false)
@@ -522,7 +509,7 @@ func (p *Parser) binary() (Node, error) {
r := values.Pop()
l := values.Pop()
opToken := ops.Pop()
- op := tokenToBinaryOperation(opToken.Kind)
+ op := tokenToBinaryOperation(opToken.Type)
start, _ := l.Bounds()
_, end := r.Bounds()
@@ -537,12 +524,12 @@ func (p *Parser) binary() (Node, error) {
})
}
- for isBinaryOperator(p.state.curr.Kind) {
- for ops.Current > 0 && binaryPrecedence(p.state.curr.Kind) <= binaryPrecedence(ops.Peek().Kind) {
+ for isBinaryOperator(p.curr.Type) {
+ for ops.Current > 0 && binaryPrecedence(p.curr.Type) <= binaryPrecedence(ops.Peek().Type) {
reduce()
}
- ops.Push(p.state.curr)
+ ops.Push(p.curr)
p.advance()
v, err := p.chain()
@@ -571,16 +558,16 @@ func (p *Parser) chain() (Node, error) {
if err = p.expect(TokenName, "can only access properties by name"); err != nil {
return nil, err
}
- name := p.state.prev
+ name := p.prev
f = &AccessNode{
f,
- p.state.prev,
+ p.prev,
name.Start,
name.End,
}
- if p.state.curr.Kind == TokenOpenParenthesis {
+ if p.curr.Type == TokenOpenParenthesis {
args, err := p.parseArgs()
if err != nil {
return nil, err
@@ -590,11 +577,11 @@ func (p *Parser) chain() (Node, error) {
f,
args,
name.Start,
- p.state.prev.End,
+ p.prev.End,
}
}
- } else if p.state.curr.Kind == TokenOpenParenthesis {
- start := p.state.curr.Start
+ } else if p.curr.Type == TokenOpenParenthesis {
+ start := p.curr.Start
args, err := p.parseArgs()
if err != nil {
return nil, err
@@ -605,10 +592,10 @@ func (p *Parser) chain() (Node, error) {
args,
start,
- p.state.prev.End,
+ p.prev.End,
}
} else if p.accept(TokenOpenBracket) {
- start := p.state.prev.Start
+ start := p.prev.Start
index, err := p.expression(false)
if err != nil {
@@ -623,7 +610,7 @@ func (p *Parser) chain() (Node, error) {
f,
index,
start,
- p.state.prev.End,
+ p.prev.End,
}
} else {
break
@@ -634,71 +621,71 @@ func (p *Parser) chain() (Node, error) {
}
func (p *Parser) factor() (Node, error) {
- switch (*p.state.curr).Kind {
+ switch (*p.curr).Type {
case TokenString:
p.advance()
return &StringNode{
- (*p.state.prev).Lexeme[1 : len((*p.state.prev).Lexeme)-1],
- (*p.state.prev).Lexeme,
- p.state.prev.Start,
- p.state.prev.End,
+ (*p.prev).Lexeme[1 : len((*p.prev).Lexeme)-1],
+ (*p.prev).Lexeme,
+ p.prev.Start,
+ p.prev.End,
}, nil
case TokenInteger:
p.advance()
- num, success := new(big.Int).SetString(p.state.prev.Lexeme, 10)
+ num, success := new(big.Int).SetString(p.prev.Lexeme, 10)
if !success {
- return nil, p.error(fmt.Sprintf("cannot parse integer base 10: %s", p.state.prev.Lexeme), p.state.prev)
+ return nil, p.error(fmt.Sprintf("cannot parse integer base 10: %s", p.prev.Lexeme), p.prev)
}
return &IntegerNode{
num,
- p.state.prev.Start,
- p.state.prev.End,
+ p.prev.Start,
+ p.prev.End,
}, nil
case TokenFloat:
p.advance()
- num, err := strconv.ParseFloat((*p.state.prev).Lexeme, FloatSize)
+ num, err := strconv.ParseFloat((*p.prev).Lexeme, FloatSize)
if err != nil {
- return nil, p.error(fmt.Sprintf("Error parsing number: %v", err), p.state.prev)
+ return nil, p.error(fmt.Sprintf("Error parsing number: %v", err), p.prev)
}
return &FloatNode{
num,
- p.state.prev.Start,
- p.state.prev.End,
+ p.prev.Start,
+ p.prev.End,
}, nil
case TokenHexadecimal:
p.advance()
- start := (*p.state.prev).Start
- num, ok := new(big.Int).SetString(p.state.prev.Lexeme[2:], 16)
+ start := (*p.prev).Start
+ num, ok := new(big.Int).SetString(p.prev.Lexeme[2:], 16)
if !ok {
- return nil, p.error(fmt.Sprintf("cannot parse hexadecimal: %v", p.state.prev.Lexeme), p.state.prev)
+ return nil, p.error(fmt.Sprintf("cannot parse hexadecimal: %v", p.prev.Lexeme), p.prev)
}
return &IntegerNode{
num,
start,
- p.state.prev.End,
+ p.prev.End,
}, nil
case TokenTrue:
p.advance()
return &BooleanNode{
true,
- p.state.prev.Start,
- p.state.prev.End,
+ p.prev.Start,
+ p.prev.End,
}, nil
case TokenFalse:
p.advance()
return &BooleanNode{
false,
- p.state.prev.Start,
- p.state.prev.End,
+ p.prev.Start,
+ p.prev.End,
}, nil
case TokenNil:
@@ -707,7 +694,7 @@ func (p *Parser) factor() (Node, error) {
case TokenOpenBracket:
p.advance()
- start := p.state.prev.Start
+ start := p.prev.Start
// TODO: find better solution; current one is messy
// Maybe perform better analysis to determine the kind of the list...
@@ -721,12 +708,12 @@ func (p *Parser) factor() (Node, error) {
[]Node{},
s,
start,
- p.state.prev.End,
+ p.prev.End,
}, nil
}
- oldIgnoreNewline := p.state.ignoreNewLine
- p.state.ignoreNewLine = true
+ oldIgnoreNewline := p.ignoreNewLine
+ p.ignoreNewLine = true
var values []Node
for !p.accept(TokenCloseBracket) {
@@ -744,19 +731,19 @@ func (p *Parser) factor() (Node, error) {
values = append(values, value)
}
- p.state.ignoreNewLine = oldIgnoreNewline
+ p.ignoreNewLine = oldIgnoreNewline
return &ListNode{
values,
nil,
start,
- p.state.prev.End,
+ p.prev.End,
}, nil
// unary minus
case TokenMinus:
p.advance()
- op := p.state.prev
+ op := p.prev
f, err := p.factor()
if err != nil {
@@ -767,12 +754,12 @@ func (p *Parser) factor() (Node, error) {
f,
op,
op.Start,
- p.state.prev.End,
+ p.prev.End,
}, nil
case TokenBang:
p.advance()
- op := p.state.prev
+ op := p.prev
v, err := p.factor()
if err != nil {
@@ -784,16 +771,16 @@ func (p *Parser) factor() (Node, error) {
v,
op,
op.Start,
- p.state.prev.End,
+ p.prev.End,
}, nil
case TokenName:
p.advance()
- name := (*p.state.prev).Lexeme
- start := p.state.prev.Start
- nameEnd := p.state.prev.End
+ name := (*p.prev).Lexeme
+ start := p.prev.Start
+ nameEnd := p.prev.End
- if p.state.curr.Kind == TokenOpenParenthesis {
+ if p.curr.Type == TokenOpenParenthesis {
args, err := p.parseArgs()
if err != nil {
return nil, err
@@ -807,7 +794,7 @@ func (p *Parser) factor() (Node, error) {
},
args,
start,
- p.state.prev.End,
+ p.prev.End,
}, nil
}
@@ -819,11 +806,11 @@ func (p *Parser) factor() (Node, error) {
case TokenFunc:
p.advance()
- start := p.state.prev.Start
+ start := p.prev.Start
var name *Token
if p.accept(TokenName) { // can be unnamed, but accept name if it is named
- name = p.state.prev
+ name = p.prev
}
params, err := p.parseParams()
@@ -855,7 +842,7 @@ func (p *Parser) factor() (Node, error) {
yield,
logic,
start,
- p.state.prev.End,
+ p.prev.End,
}
if name != nil {
@@ -864,7 +851,7 @@ func (p *Parser) factor() (Node, error) {
fn,
true,
start,
- p.state.prev.End,
+ p.prev.End,
}, nil
}
@@ -872,67 +859,11 @@ func (p *Parser) factor() (Node, error) {
case TokenOpenParenthesis:
p.advance()
- start := p.state.prev.Start
- oldCare := p.state.ignoreNewLine
- p.state.ignoreNewLine = true
- p.skipNewLines()
+ start := p.prev.Start
// we're inside an object
- key := p.state.curr
- if p.acceptSeq(TokenName, TokenColon) {
- entries := map[string]Node{}
-
- for len(entries) == 0 || !p.accept(TokenCloseParenthesis) {
- if len(entries) != 0 {
- p.skipNewLines()
- key = p.state.curr
- if !p.acceptSeq(TokenName, TokenColon) {
- return nil, p.error("expected a record name", key)
- }
- }
-
- name := key.Lexeme
-
- if _, ok := entries[name]; ok {
- return nil, p.error("duplicate key; already defined.", key)
- }
-
- if p.accept(TokenComma) || p.accept(TokenCloseParenthesis) {
- entries[name] = &ReferenceNode{
- name,
- key.Start,
- key.End,
- }
-
- if p.state.prev.Kind == TokenCloseParenthesis {
- break
- }
-
- continue
- } else {
- x, err := p.expression(false)
- if err != nil {
- return nil, err
- }
-
- entries[name] = x
- }
-
- if !p.accept(TokenComma) {
- if err := p.expect(TokenCloseParenthesis, "record must be closed"); err != nil {
- return nil, err
- }
-
- break
- }
- }
-
- p.state.ignoreNewLine = oldCare
- return &RecordNode{
- entries,
- start,
- p.state.prev.End,
- }, nil
+ if p.acceptAll(TokenName, TokenColon) {
+ return nil, p.error("objects are not implemented yet (TBD)", p.prev)
}
v, err := p.expression(false)
@@ -945,7 +876,6 @@ func (p *Parser) factor() (Node, error) {
return nil, err
}
- p.state.ignoreNewLine = oldCare
return v, nil
}
@@ -967,27 +897,26 @@ func (p *Parser) factor() (Node, error) {
}
}
- p.state.ignoreNewLine = oldCare
return &TupleNode{
items,
start,
- p.state.prev.End,
+ p.prev.End,
}, nil
case TokenBreakpoint:
p.advance()
return &BreakpointNode{
- p.state.prev.Start,
- p.state.prev.End,
+ p.prev.Start,
+ p.prev.End,
}, nil
case TokenOpenBrace:
return p.expression(true)
default:
- return nil, p.error(fmt.Sprintf("invalid factor %s", p.state.curr), p.state.curr)
+ return nil, p.error(fmt.Sprintf("invalid factor %s", p.curr), p.curr)
}
}
@@ -1027,7 +956,7 @@ func (p *Parser) parseParams() ([]FunctionParameter, error) {
params := make([]FunctionParameter, 0)
if p.accept(TokenName) {
- name := (*p.state.prev).Lexeme
+ name := (*p.prev).Lexeme
if err := p.expect(TokenColon, "parameters must have a type separated by a colon"); err != nil {
return nil, err
}
@@ -1048,7 +977,7 @@ func (p *Parser) parseParams() ([]FunctionParameter, error) {
if err := p.expect(TokenName, "parameters must have a name (cannot have trailing comma)"); err != nil {
return nil, err
}
- name = (*p.state.prev).Lexeme
+ name = (*p.prev).Lexeme
if err := p.expect(TokenColon, "parameters must have a type separated by a colon"); err != nil {
return nil, err
}
@@ -1076,42 +1005,9 @@ func (p *Parser) parseSignature() (TypeSignature, error) {
var s TypeSignature
if p.accept(TokenOpenParenthesis) {
- oldCare := p.state.ignoreNewLine
- p.state.ignoreNewLine = true
- p.skipNewLines()
-
// we're inside an object
- name := p.state.curr
- if p.acceptSeq(TokenName, TokenColon) {
- entries := map[string]TypeSignature{}
-
- for len(entries) == 0 || !p.accept(TokenCloseParenthesis) {
- if len(entries) != 0 {
- p.skipNewLines()
- name = p.state.curr
- if !p.acceptSeq(TokenName, TokenColon) {
- return nil, p.error("expected record member", p.state.curr)
- }
- }
-
- sig, err := p.parseSignature()
- if err != nil {
- return nil, err
- }
-
- entries[name.Lexeme] = sig
-
- if !p.accept(TokenComma) {
- if err := p.expect(TokenCloseParenthesis, "record must be closed"); err != nil {
- return nil, err
- }
- break
- }
- }
-
- return &RecordSignature{
- entries,
- }, nil
+ if p.acceptAll(TokenName, TokenColon) {
+ return nil, p.error("objects are not implemented yet (TBD)", p.prev)
}
v, err := p.parseSignature()
@@ -1147,8 +1043,6 @@ func (p *Parser) parseSignature() (TypeSignature, error) {
items,
}
}
-
- p.state.ignoreNewLine = oldCare
} else if p.accept(TokenFunc) {
if err := p.expect(TokenOpenParenthesis, "func signature must have parentheses for parameters"); err != nil {
return nil, err
@@ -1201,7 +1095,7 @@ func (p *Parser) parseSignature() (TypeSignature, error) {
if err := p.expect(TokenName, "type must be a name"); err != nil {
return nil, err
}
- name := (*p.state.prev).Lexeme
+ name := (*p.prev).Lexeme
switch name {
case "str":
@@ -1236,8 +1130,3 @@ func (p *Parser) parseSignature() (TypeSignature, error) {
return s, nil
}
-
-func (p *Parser) skipNewLines() {
- for p.accept(TokenNewLine) {
- }
-}
diff --git a/core/parser_test.go b/core/parser_test.go
index b58330b..79b60c9 100644
--- a/core/parser_test.go
+++ b/core/parser_test.go
@@ -15,7 +15,7 @@ func TestNewParser(t *testing.T) {
t.Fatal("parser should not be nil")
}
- if p.state.pos != 0 {
+ if p.pos != 0 {
t.Error("parser should initialize position at 0")
}
@@ -715,95 +715,6 @@ func GetTokenTestData() map[string]TokenTestData {
0, 0,
},
},
- "record/single": {
- []Token{
- NewToken(TokenOpenParenthesis, 0, 0, 0, "("),
- NewToken(TokenName, 0, 0, 1, "a"),
- NewToken(TokenColon, 0, 0, 0, ":"),
- NewToken(TokenInteger, 0, 0, 0, "2"),
- NewToken(TokenCloseParenthesis, 0, 0, 0, ")"),
- NewToken(TokenEOF, 0, 0, 0, ""),
- },
- &BlockNode{
- []Node{
- &RecordNode{
- map[string]Node{
- "a": &IntegerNode{
- big.NewInt(2),
- 0, 0,
- },
- },
-
- 0, 0,
- },
- },
- 0, 0,
- },
- },
- "record/multiple": {
- []Token{
- NewToken(TokenOpenParenthesis, 0, 0, 0, "("),
- NewToken(TokenName, 0, 0, 1, "a"),
- NewToken(TokenColon, 0, 0, 0, ":"),
- NewToken(TokenInteger, 0, 0, 0, "2"),
- NewToken(TokenComma, 0, 0, 0, ","),
- NewToken(TokenName, 0, 0, 1, "b"),
- NewToken(TokenColon, 0, 0, 0, ":"),
- NewToken(TokenInteger, 0, 0, 0, "4"),
- NewToken(TokenCloseParenthesis, 0, 0, 0, ")"),
- NewToken(TokenEOF, 0, 0, 0, ""),
- },
- &BlockNode{
- []Node{
- &RecordNode{
- map[string]Node{
- "a": &IntegerNode{
- big.NewInt(2),
- 0, 0,
- },
- "b": &IntegerNode{
- big.NewInt(4),
- 0, 0,
- },
- },
-
- 0, 0,
- },
- },
- 0, 0,
- },
- },
- "record/shorthand": {
- []Token{
- NewToken(TokenOpenParenthesis, 0, 0, 0, "("),
- NewToken(TokenName, 0, 0, 1, "a"),
- NewToken(TokenColon, 0, 0, 0, ":"),
- NewToken(TokenComma, 0, 0, 0, ","),
- NewToken(TokenName, 0, 0, 1, "b"),
- NewToken(TokenColon, 0, 0, 0, ":"),
- NewToken(TokenCloseParenthesis, 0, 0, 0, ")"),
- NewToken(TokenEOF, 0, 0, 0, ""),
- },
- &BlockNode{
- []Node{
- &RecordNode{
- map[string]Node{
- "a": &ReferenceNode{
- "a",
- 0, 0,
- },
- "b": &ReferenceNode{
- "b",
- 0, 0,
- },
- },
-
- 0, 0,
- },
- },
- 0, 0,
- },
- },
}
}
@@ -1001,23 +912,6 @@ func NodeEquality(t *testing.T, n1 Node, n2 Node) {
NodeEquality(t, v1, t2.items[i])
}
- case RecordNodeType:
- r1 := n1.(*RecordNode)
- r2 := n2.(*RecordNode)
-
- if len(r1.entries) != len(r2.entries) {
- t.Fatalf("Record node entries count does not match")
- }
-
- for i, v1 := range r1.entries {
- t.Logf("Checking item %s", i)
- if v2, ok := r2.entries[i]; ok {
- NodeEquality(t, v1, v2)
- } else {
- t.Errorf("Record node entry %s from first does not exist in other", i)
- }
- }
-
default:
panic("unimplemented node equality")
}
@@ -1045,55 +939,25 @@ func TestParser_Parse(t *testing.T) {
}
}
-func TestParser_AcceptSeq(t *testing.T) {
+func TestParser_AcceptAll(t *testing.T) {
p := NewParser("a:", []string{}, []Token{
NewToken(TokenName, 0, 1, 0, "a"),
- NewToken(TokenColon, 1, 2, 0, ":"),
- NewToken(TokenEOF, 2, 2, 0, ""),
+ NewToken(TokenColon, 1, 2, 0, "a"),
})
- // initialize
- p.advance()
-
- if !p.acceptSeq(TokenName, TokenColon) {
+ if !p.acceptAll(TokenName, TokenColon) {
t.Fatalf("tokens were not accepted")
}
t.Logf("tokens were accepted")
}
-func TestParser_AcceptSeqAndAfter(t *testing.T) {
- p := NewParser("a: 1", []string{}, []Token{
- NewToken(TokenName, 0, 1, 0, "a"),
- NewToken(TokenColon, 1, 2, 0, ":"),
- NewToken(TokenInteger, 3, 4, 0, "1"),
- NewToken(TokenEOF, 4, 4, 0, ""),
- })
-
- // initialize
- p.advance()
-
- if !p.acceptSeq(TokenName, TokenColon) {
- t.Fatalf("seq tokens were not accepted")
- }
-
- if !p.accept(TokenInteger) {
- t.Fatalf("integer was not accepted")
- }
-
- t.Logf("tokens were accepted")
-}
-
-func TestParser_AcceptSeq_TooFew(t *testing.T) {
+func TestParser_AcceptAll_TooFew(t *testing.T) {
p := NewParser("a", []string{}, []Token{
NewToken(TokenName, 0, 1, 0, "a"),
- NewToken(TokenEOF, 1, 1, 0, ""),
})
- // initialize
- p.advance()
-
- if p.acceptSeq(TokenName, TokenColon) {
+ if p.acceptAll(TokenName, TokenColon) {
t.Fatalf("tokens were incorrectly accepted")
}
diff --git a/core/stack_test.go b/core/stack_test.go
index 2bc9f86..41f3d79 100644
--- a/core/stack_test.go
+++ b/core/stack_test.go
@@ -2,19 +2,18 @@ package core
import (
"fmt"
- "slices"
"testing"
)
func CompareScope(t *testing.T, expectedScope []map[string]Value, actualScope *Scope) {
s := actualScope
- for _, e := range slices.Backward(expectedScope) {
+ for i := len(expectedScope) - 1; i >= 0; i-- {
if s == nil {
t.Fatal("scope cut unexpecetantly short")
}
- for name, value := range e {
+ for name, value := range expectedScope[i] {
v, ok := s.current[name]
if !ok {
t.Errorf("variable %s not found in correct scope", name)
diff --git a/core/types.go b/core/types.go
index 81dafd8..13f9e1b 100644
--- a/core/types.go
+++ b/core/types.go
@@ -21,7 +21,6 @@ const (
TypeComposite
TypeInner
TypeNamed
- TypeRecord
)
func (t Type) String() string {
@@ -50,11 +49,9 @@ func (t Type) String() string {
return "composite"
case TypeInner:
return "inner"
- case TypeRecord:
- return "record"
- default:
- panic(fmt.Sprintf("unsupported string conversion for type %v", int(t)))
}
+
+ panic(fmt.Sprintf("unsupported string conversion for type %v", int(t)))
}
func SignatureOf(v Value) TypeSignature {
@@ -487,27 +484,6 @@ func quickComposite(a ...TypeSignature) TypeSignature {
return s
}
-func simplifyComposite(a TypeSignature) TypeSignature {
- var atoms []TypeSignature
-
- s := NewStack[TypeSignature](16)
- s.Push(a)
-
- for s.Current > 0 {
- i := s.Pop()
-
- c, ok := i.(*CompositeSignature)
- if !ok {
-
- atoms = append(atoms, i)
- } else {
- s.Push(c.A, c.B)
- }
- }
-
- return quickComposite(atoms...)
-}
-
type InnerSignature struct{}
func (*InnerSignature) Type() Type {
@@ -545,56 +521,3 @@ func (s *NamedSignature) Equal(t TypeSignature) bool {
func (s *NamedSignature) String() string {
return s.Name
}
-
-type RecordSignature struct {
- Entries map[string]TypeSignature
-}
-
-func (*RecordSignature) Type() Type {
- return TypeRecord
-}
-
-func (s *RecordSignature) Contains(t TypeSignature) bool {
- if t.Type() != TypeRecord {
- return false
- }
-
- rs := t.(*RecordSignature)
-
- /*
- // not quite sure about this one
- if len(s.Entries) != len(rs.Entries) {
- return false
- }
- */
-
- for k, v := range s.Entries {
- is, ok := rs.Entries[k]
- if !ok {
- return false
- }
-
- if !v.Contains(is) {
- return false
- }
- }
-
- return true
-}
-
-func (s *RecordSignature) Equal(t TypeSignature) bool {
- return s.Contains(t) && len(t.(*RecordSignature).Entries) == len(s.Entries)
-}
-
-func (s *RecordSignature) String() string {
- b := strings.Builder{}
- b.WriteString("(")
-
- for name, kind := range s.Entries {
- b.WriteString(fmt.Sprintf("%s: %s, ", name, kind))
- }
-
- b.WriteString(")")
-
- return b.String()
-}
diff --git a/core/values.go b/core/values.go
index e0cee7c..94c666f 100644
--- a/core/values.go
+++ b/core/values.go
@@ -22,7 +22,7 @@ const (
ObjectValueType
FunctionValueType
BuiltinFunctionValueType
- RecordValueType
+ VariableValueType
)
func (v ValueType) String() string {
@@ -47,15 +47,15 @@ func (v ValueType) String() string {
return "function"
case BuiltinFunctionValueType:
return "builtin function"
- case RecordValueType:
- return "record"
+ case VariableValueType:
+ return "variable"
}
return "undefined"
}
// GoToValue convert go values to anglais VM-values. Works for some values (nil, bool, float64, int, string, slices, maps)
-func GoToValue(gov any) Value {
+func GoToValue(gov interface{}) Value {
switch v := gov.(type) {
case nil:
return &NilValue{}
@@ -79,7 +79,7 @@ func GoToValue(gov any) Value {
return &StringValue{
v,
}
- case map[string]any:
+ case map[string]interface{}:
values := map[string]Value{}
for key, value := range v {
values[key] = GoToValue(value)
@@ -117,12 +117,8 @@ type Value interface {
// Get a member from the value. An error is returned if the member does not exist
Get(string) (Value, error)
- // Copy create a copy of the value. A copy is a direct copy for small data (numbers) and a copy of pointer
- // for bigger data (lists, tuples, dicts)
- Copy() Value
-
- // Clone create a clone of the value. A clone is new data for all data.
- //Clone() Value
+ // Clone create a clone of the value. The returned value is a pointer to a new value of the same type as the value.
+ Clone() Value
}
type NilValue struct{}
@@ -147,7 +143,7 @@ func (v *NilValue) Get(_ string) (Value, error) {
return nil, errors.New("nil has no properties")
}
-func (v *NilValue) Copy() Value {
+func (v *NilValue) Clone() Value {
return &NilValue{}
}
@@ -179,7 +175,7 @@ func (v *BoolValue) Get(_ string) (Value, error) {
return nil, errors.New("booleans have no properties")
}
-func (v *BoolValue) Copy() Value {
+func (v *BoolValue) Clone() Value {
return &BoolValue{
v.Boolean,
}
@@ -262,11 +258,11 @@ func (v *ObjectValue) Get(key string) (Value, error) {
}
}
-func (v *ObjectValue) Copy() Value {
+func (v *ObjectValue) Clone() Value {
m := make(map[string]Value, len(v.Members))
for name, mem := range v.Members {
- m[name] = mem.Copy()
+ m[name] = mem.Clone()
}
return &ObjectValue{
@@ -307,7 +303,7 @@ func (v *FloatValue) Get(_ string) (Value, error) {
return nil, errors.New("numbers have no properties")
}
-func (v *FloatValue) Copy() Value {
+func (v *FloatValue) Clone() Value {
return &FloatValue{
v.Number,
}
@@ -338,7 +334,7 @@ func (v *IntegerValue) Get(_ string) (Value, error) {
return nil, errors.New("numbers have no properties")
}
-func (v *IntegerValue) Copy() Value {
+func (v *IntegerValue) Clone() Value {
return &IntegerValue{
new(big.Int).Set(v.Number),
}
@@ -387,7 +383,7 @@ var StringPrototype = map[string]*BuiltinFunctionValue{
}
if prev != len(str) {
- out = append(out, &StringValue{str[prev:]})
+ out = append(out, &StringValue{str[prev:len(str)]})
}
return &ListValue{out}, nil
@@ -431,7 +427,7 @@ func (v *StringValue) Get(key string) (Value, error) {
return nil, errors.New(fmt.Sprintf("string has no property \"%s\"", key))
}
-func (v *StringValue) Copy() Value {
+func (v *StringValue) Clone() Value {
return &StringValue{
v.Text,
}
@@ -447,17 +443,16 @@ func (v *ListValue) Type() ValueType {
}
func (v *ListValue) String() string {
- var out strings.Builder
- out.WriteString("[")
+ out := "["
for i, item := range v.Items {
if i != 0 {
- out.WriteString(", ")
+ out += ", "
}
- out.WriteString(item.DebugString())
+ out += item.DebugString()
}
- out.WriteString("]")
+ out += "]"
- return out.String()
+ return out
}
func (v *ListValue) DebugString() string {
@@ -599,9 +594,15 @@ func (v *ListValue) Get(key string) (Value, error) {
return nil, errors.New(fmt.Sprintf("list has no property \"%s\"", key))
}
-func (v *ListValue) Copy() Value {
+func (v *ListValue) Clone() Value {
+ n := make([]Value, len(v.Items))
+
+ for i, item := range v.Items {
+ n[i] = item.Clone()
+ }
+
return &ListValue{
- v.Items,
+ n,
}
}
@@ -614,30 +615,33 @@ func (v *TupleValue) Type() ValueType {
}
func (v *TupleValue) String() string {
- var out strings.Builder
- out.WriteString("(")
+ out := "("
for i, item := range v.Items {
if i != 0 {
- out.WriteString(", ")
+ out += ", "
}
- out.WriteString(item.DebugString())
+ out += item.DebugString()
}
if len(v.Items) <= 1 {
- out.WriteString(",")
+ out += ","
}
- out.WriteString(")")
+ out += ")"
- return out.String()
+ return out
}
func (v *TupleValue) DebugString() string {
return v.String()
}
-func (v *TupleValue) Copy() Value {
+func (v *TupleValue) Clone() Value {
+ n := make([]Value, len(v.Items))
+ for i, item := range v.Items {
+ n[i] = item.Clone()
+ }
return &TupleValue{
- v.Items,
+ n,
}
}
@@ -657,7 +661,7 @@ func (v *TupleValue) Equals(other Value) bool {
}
var TuplePrototype = map[string]*BuiltinFunctionValue{
- "at": {
+ "at": &BuiltinFunctionValue{
"at",
&FunctionSignature{
[]TypeSignature{&IntegerSignature{}},
@@ -714,7 +718,7 @@ func (v *FunctionValue) Get(_ string) (Value, error) {
return nil, errors.New("functions have no properties")
}
-func (v *FunctionValue) Copy() Value {
+func (v *FunctionValue) Clone() Value {
return &FunctionValue{
v.Name,
v.Params,
@@ -754,7 +758,7 @@ func (v *BuiltinFunctionValue) Get(_ string) (Value, error) {
return nil, errors.New("functions have no properties")
}
-func (v *BuiltinFunctionValue) Copy() Value {
+func (v *BuiltinFunctionValue) Clone() Value {
return &BuiltinFunctionValue{
v.Name,
v.Signature,
@@ -763,82 +767,3 @@ func (v *BuiltinFunctionValue) Copy() Value {
v.Constant,
}
}
-
-type RecordValue struct {
- Entries map[string]Value
-}
-
-func (v *RecordValue) Type() ValueType {
- return RecordValueType
-}
-
-func (v *RecordValue) String() string {
- sb := strings.Builder{}
-
- sb.WriteString("(")
-
- n := 0
- for prop, value := range v.Entries {
- if n != 0 {
- sb.WriteString(", ")
- }
-
- sb.WriteString(prop)
- sb.WriteString(": ")
- sb.WriteString(value.DebugString())
-
- n += 1
- }
-
- if n == 1 {
- sb.WriteString(",")
- }
-
- sb.WriteString(")")
-
- return sb.String()
-}
-
-func (v *RecordValue) DebugString() string {
- return v.String()
-}
-
-func (v *RecordValue) Copy() Value {
- return &RecordValue{
- v.Entries,
- }
-}
-
-func (v *RecordValue) Equals(other Value) bool {
- if other.Type() != RecordValueType {
- return false
- }
-
- r := other.(*RecordValue)
-
- if len(r.Entries) != len(v.Entries) {
- return false
- }
-
- for key, val := range v.Entries {
- oth, ok := r.Entries[key]
- if !ok {
- return false
- }
-
- if !val.Equals(oth) {
- return false
- }
- }
-
- return true
-}
-
-func (v *RecordValue) Get(key string) (Value, error) {
- val, ok := v.Entries[key]
- if !ok {
- return nil, errors.New(fmt.Sprintf("record has no property \"%s\"", key))
- }
-
- return val, nil
-}
diff --git a/core/vm.go b/core/vm.go
index 068b1c6..17a1a62 100644
--- a/core/vm.go
+++ b/core/vm.go
@@ -9,7 +9,6 @@ import (
"math"
"math/big"
"os"
- "slices"
"strconv"
"strings"
)
@@ -127,7 +126,7 @@ const (
// InstructionAppend Append to a list. stack: (... > list > item) => (... > list)
InstructionAppend
// InstructionFormList Form items on the stack into a list. The 2 bytes after the instructions are the amount of
- // items to include. The order is reversed compared to on the stack; the top value on the stack is the last in the
+ // items to include) The order is reversed compared to on the stack; the top value on the stack is the last in the
// list.
InstructionFormList
// InstructionConcatLists concatenate lists, producing a new list with the values of both lists. Pops two lists.
@@ -140,12 +139,6 @@ const (
// being the last item in the tuple.
InstructionDestructureTuple
- // InstructionNewRecord Create a new empty record.
- InstructionNewRecord
- // InstructionSetRecordItem Set the value of an item in the record, and create it if it does not already exist.
- // [..., record, item]; the following byte should be the index of a string constant with the name of the property.
- InstructionSetRecordItem
-
// InstructionIndexList index into a list. The lower item is the container, and the top item
// is the index. [..., container, index] -> [..., item]
InstructionIndexList
@@ -153,14 +146,10 @@ const (
// is the index. [..., container, index] -> [..., item]
InstructionIndexTuple
// InstructionIndexString index into a string. The lower item is the container, and the top item
- // is the index. [..., container, index] -> [..., item]. Produces a new string with only the character
- // at the indexed position
+ // is the index. [..., container, index] -> [..., item]. Produces a new string with the character
+ // at the position
InstructionIndexString
- // InstructionSetIndexList set the item at a given index in a list.
- // [..., item, container, index] -> [..., item]
- InstructionSetIndexList
-
// InstructionBreakpoint for debugging purposes
InstructionBreakpoint
)
@@ -273,14 +262,6 @@ func (b Bytecode) String() string {
return "INDEX_TUPLE"
case InstructionDestructureTuple:
return "DESTRUCTURE_TUPLE"
- case InstructionModInt:
- return "MOD_INT"
- case InstructionNewRecord:
- return "NEW_RECORD"
- case InstructionSetRecordItem:
- return "SET_PROPERTY"
- case InstructionIndexString:
- return "INDEX_STRING"
}
return "UNDEFINED"
}
@@ -643,7 +624,7 @@ var DefaultGlobals = map[string]Value{
n, _ := v.Number.Float64()
return &FloatValue{n}, nil
case *FloatValue:
- return v.Copy(), nil
+ return v.Clone(), nil
case *StringValue:
num, err := strconv.ParseFloat(v.Text, FloatSize)
if err != nil {
@@ -927,8 +908,8 @@ func (vm *VM) Next() bool {
vm.scope = f.Scope
vm.descend()
- for _, v := range slices.Backward(f.Params) {
- vm.addVar(v.Name, vm.Stack.Pop())
+ for i := len(f.Params) - 1; i >= 0; i-- {
+ vm.addVar(f.Params[i].Name, vm.Stack.Pop())
}
if f.Parent != nil {
@@ -983,7 +964,7 @@ func (vm *VM) Next() bool {
vm.Stack.Push(v)
case InstructionSetLocal:
- value := vm.Stack.Peek().Copy()
+ value := vm.Stack.Peek().Clone()
name := vm.GetConstant(vm.NextByte()).(*StringValue).Text
vm.setVar(name, value)
@@ -991,7 +972,7 @@ func (vm *VM) Next() bool {
case InstructionDeclareLocal:
vm.addVar(
vm.GetConstant(vm.NextByte()).(*StringValue).Text,
- vm.Stack.Peek().Copy(),
+ vm.Stack.Peek().Clone(),
)
case InstructionGetGlobal:
@@ -1075,7 +1056,7 @@ func (vm *VM) Next() bool {
vm.Stack.Push(r, l)
case InstructionDuplicate:
- vm.Stack.Push(vm.Stack.Peek().Copy())
+ vm.Stack.Push(vm.Stack.Peek().Clone())
case InstructionAccessProperty:
source := vm.Stack.Pop()
@@ -1095,18 +1076,6 @@ func (vm *VM) Next() bool {
vm.Stack.Push(member)
- case InstructionSetRecordItem:
- i := vm.Stack.Pop()
- prop := vm.ReadConstant().(*StringValue)
- r := vm.Stack.Peek().(*RecordValue)
-
- r.Entries[prop.Text] = i
-
- case InstructionNewRecord:
- vm.Stack.Push(&RecordValue{
- map[string]Value{},
- })
-
case InstructionIndexList:
i := vm.Stack.Pop().(*IntegerValue)
l := vm.Stack.Pop().(*ListValue)
@@ -1117,7 +1086,7 @@ func (vm *VM) Next() bool {
vm.error(fmt.Sprintf("index %d out of bounds", n))
}
- vm.Stack.Push(l.Items[n].Copy())
+ vm.Stack.Push(l.Items[n].Clone())
case InstructionIndexTuple:
i := vm.Stack.Pop().(*IntegerValue)
@@ -1129,7 +1098,7 @@ func (vm *VM) Next() bool {
vm.error(fmt.Sprintf("index %d out of bounds", n))
}
- vm.Stack.Push(t.Items[n].Copy())
+ vm.Stack.Push(t.Items[n].Clone())
case InstructionIndexString:
i := vm.Stack.Pop().(*IntegerValue)
@@ -1143,18 +1112,6 @@ func (vm *VM) Next() bool {
vm.Stack.Push(&StringValue{string(s.Text[n])})
- case InstructionSetIndexList:
- n := vm.Stack.Pop().(*IntegerValue)
- l := vm.Stack.Pop().(*ListValue)
-
- i := n.Number.Int64()
-
- if i < 0 || int64(len(l.Items)) <= i {
- vm.error(fmt.Sprintf("index %d out of bounds", i))
- }
-
- l.Items[i] = vm.Stack.Peek().Copy()
-
case InstructionBreakpoint:
/*
// I'm keeping this
@@ -1301,7 +1258,7 @@ func (vm *VM) HasNext() bool {
}
func (vm *VM) GetConstant(id Bytecode) Value {
- return vm.chunk.Constants[id].Copy()
+ return vm.chunk.Constants[id].Clone()
}
func (vm *VM) ReadConstant() Value {
diff --git a/examples/bad.ang b/examples/bad.ang
deleted file mode 100644
index 80c9cb7..0000000
--- a/examples/bad.ang
+++ /dev/null
@@ -1,40 +0,0 @@
-import "lib/math.ang"
-
-primes := [2]
-
-func is_prime(x: number) boolean {
- i := 0
- while i < primes.length() && primes.at(i)*primes.at(i) < x {
- if mod(x, primes.at(i)) == 0 {
- return false
- }
- i = i + 1
- }
-
- return true
-}
-
-n := 1
-max := 100000
-
-while n < max {
- n = n + 2
-
- if is_prime(n) {
- primes.append(n)
-
- # Update counter
- print(char(0x0D))
- print(str(n))
- print("/")
- print(str(max))
- print(char(0x09))
- print(str(roundd(n/max*100, 2)))
- print("%")
- print(char(0x09))
- print(str(primes.length()))
- print(" primes")
- }
-}
-
-write(str(primes))
diff --git a/examples/blemish.ang b/examples/blemish.ang
deleted file mode 100644
index ee25ddf..0000000
--- a/examples/blemish.ang
+++ /dev/null
@@ -1,20 +0,0 @@
-fn fib(n: int) -> int {
- if n < 2 {
- n
- } else {
- fib(n-1) + fib(n-2)
- }
-}
-
-println(fib(2))
-
-fn other(n: int) -> int {
- if n <= 0 {
- n
- } else {
- println(n)
- (n - 1)
- }
-}
-
-println(other(2))
diff --git a/examples/chars.ang b/examples/chars.ang
deleted file mode 100644
index 343ccee..0000000
--- a/examples/chars.ang
+++ /dev/null
@@ -1,15 +0,0 @@
-
-MAX_WIDTH := 16
-
-print(" ")
-w := 1
-n := 0x21
-while n < 0xA0 {
- print(char(n))
- n = n + 1
- w = w + 1
- if w >= MAX_WIDTH {
- write("")
- w = 0
- }
-}
diff --git a/examples/codegen.ang b/examples/codegen.ang
deleted file mode 100644
index 7d44558..0000000
--- a/examples/codegen.ang
+++ /dev/null
@@ -1,24 +0,0 @@
-
-passphrase := "Hello world!".split("")
-start := [0, 0, 0]
-modulus := 10
-base := byte("!")
-
-i := 0
-n := 0
-while n < passphrase.length() {
- b := byte(passphrase.at(n))
-
- v = start.at(i) + b - base
- while v >= modulus {
- v = v - modulus
- }
-
- start.put(i, v)
-
- if i >= 3 {
- i = 0
- }
- n = n + 1
-}
-
diff --git a/examples/emoji.ang b/examples/emoji.ang
deleted file mode 100644
index 09f0cb1..0000000
--- a/examples/emoji.ang
+++ /dev/null
@@ -1,2 +0,0 @@
-
-write(char(0x12) + char(0x85) + char(0x07))
diff --git a/examples/era3.ang b/examples/era3.ang
deleted file mode 100644
index 966a458..0000000
--- a/examples/era3.ang
+++ /dev/null
@@ -1,11 +0,0 @@
-fn counter() -> (fn() -> int) {
- i := 0
-
- fn() -> int { i = i + 1 }
-}
-
-next := counter()
-
-println(next())
-println(next())
-println(next())
diff --git a/examples/fails.ang b/examples/fails.ang
deleted file mode 100644
index 8e3174d..0000000
--- a/examples/fails.ang
+++ /dev/null
@@ -1,4 +0,0 @@
-import "lib/honning.ang"
-
-write(_bell+_italic+"Hello "+_underline+"world "+_strike+"micheal"+_reset)
-
diff --git a/examples/fib.ang b/examples/fib.ang
index 4860a1e..63a432a 100644
--- a/examples/fib.ang
+++ b/examples/fib.ang
@@ -3,9 +3,14 @@
fn range(from: int, to: int) -> (fn() -> (int, bool)) {
i := from - 1
+ end := to - 1
fn() -> (int, bool) {
- (i = i+1, i+1 < to)
+ if i < end {
+ (i = i+1, true)
+ } else {
+ (-1, false)
+ }
}
}
diff --git a/examples/foo.ang b/examples/foo.ang
deleted file mode 100644
index 1047386..0000000
--- a/examples/foo.ang
+++ /dev/null
@@ -1,8 +0,0 @@
-
-fn foo(n: int) -> str {
- if n % 2 == 0 {
- "foo"
- } else {
- "bar"
- }
-}
diff --git a/examples/imp.ang b/examples/imp.ang
deleted file mode 100644
index 0ccb3ed..0000000
--- a/examples/imp.ang
+++ /dev/null
@@ -1,15 +0,0 @@
-
-func is_cool(x: number|string) boolean {
- if x == "cool" {
- return true
- } else if x == 69 {
- return true
- }
-
- return nil
-}
-
-write(str(is_cool("not cool")))
-write(str(is_cool("cool")))
-write(str(is_cool(0)))
-write(str(is_cool(69)))
diff --git a/examples/inc.ang b/examples/inc.ang
deleted file mode 100644
index 8a697a7..0000000
--- a/examples/inc.ang
+++ /dev/null
@@ -1,2 +0,0 @@
-
-foo := include "foo.ang"
diff --git a/examples/list.ang b/examples/list.ang
index d34887e..9866d3e 100644
--- a/examples/list.ang
+++ b/examples/list.ang
@@ -1,6 +1,6 @@
# Empty list
-println([]any)
+println([])
# List with items
println([3, 1, 4, 1, 5, 9, 2, 6, 5])
@@ -8,25 +8,25 @@ println([3, 1, 4, 1, 5, 9, 2, 6, 5])
# List with items of different types
println(["", "私はかっこいいです。", true, nil, nil, 1, 2])
-a := []int
+a := []
-a.push(1)
-a.push(2)
+a = a + [1]
+a = a + [2]
println(a)
-list := []int
+list := []
x := 0
for n in 0..100 {
x = x + 2*n + 1
- list.push(x)
+ list = list + [x]
}
println(list)
-println(list.map(fn(a: int) -> int {
+println(list.map(func(a) {
return a - 1
}))
println(list.length())
diff --git a/examples/massacre.ang b/examples/massacre.ang
deleted file mode 100644
index 6dbde3c..0000000
--- a/examples/massacre.ang
+++ /dev/null
@@ -1,4 +0,0 @@
-a := fn b(n: int) -> int {
- n + 1
-}
-
diff --git a/examples/network.ang b/examples/network.ang
deleted file mode 100644
index 86ba041..0000000
--- a/examples/network.ang
+++ /dev/null
@@ -1,8 +0,0 @@
-
-func get(url: string) string {
- res := request("GET", url, "")
-
- return res.text
-}
-
-write(get("https://www.neemek.com/hello.txt"))
diff --git a/examples/neutral-pH.ang b/examples/neutral-pH.ang
deleted file mode 100644
index f867a72..0000000
--- a/examples/neutral-pH.ang
+++ /dev/null
@@ -1,18 +0,0 @@
-import "../lib/math.ang"
-
-# Inputs
-c := 1.0*pow(10.0, -2.0)
-
-println(c)
-pH := -log(c, 10.0)
-
-println(pH)
-
-if pH == 7.0 {
- println("pH-en er nøytral (=7)")
-} else if pH < 7.0 {
- println("pH-en er sur (<7)")
-} else {
- println("pH-en er basisk (>7)")
-}
-
diff --git a/examples/pos.ang b/examples/pos.ang
deleted file mode 100644
index 2eda099..0000000
--- a/examples/pos.ang
+++ /dev/null
@@ -1,21 +0,0 @@
-
-type Vec2 = (float, float)
-
-fn add(a: Vec2, b: Vec2) -> Vec2 {
- (a[0] + b[0], a[1] + b[1])
-}
-
-fn sub(a: Vec2, b: Vec2) -> Vec2 {
- (a[0] - b[0], a[1] - b[1])
-}
-
-fn dot(a: Vec2, b: Vec2) -> float {
- a[0]*b[0] + a[1]*b[1]
-}
-
-u := (0.0, 1.0)
-v := (2.0, 3.0)
-
-println(add(u, v))
-println(sub(u, v))
-println(dot(u, v))
diff --git a/examples/recursive.ang b/examples/recursive.ang
index f30109f..caa0e37 100644
--- a/examples/recursive.ang
+++ b/examples/recursive.ang
@@ -1,15 +1,14 @@
# This program computes the fibonacci numbers using recursion (O(2^n))
# It is very slow
-fn fib(x: number) number {
+func fib(x: number) number {
if x <= 1 {
- x
- } else {
- fib(x - 1) + fib(x - 2)
+ return x
}
+ return fib(x - 1) + fib(x - 2)
}
n := 0
while n < 100 {
- println(fib(n))
+ write(str(fib(n)))
n = n + 1
}
diff --git a/examples/sqrt.ang b/examples/sqrt.ang
deleted file mode 100755
index f013699..0000000
--- a/examples/sqrt.ang
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/Users/neemek/Code/anglais/cli/cli run
-
-import "lib/math.ang"
-
-x := sqrt(9485739448)
-write(str(x))
diff --git a/examples/very_bad.ang b/examples/very_bad.ang
deleted file mode 100644
index dd18680..0000000
--- a/examples/very_bad.ang
+++ /dev/null
@@ -1,8 +0,0 @@
-
-a := 0
-while a < 10 {
- print(".")
- a = a + 1
-}
-
-write("")
diff --git a/examples/warp.ang b/examples/warp.ang
deleted file mode 100644
index 3186556..0000000
--- a/examples/warp.ang
+++ /dev/null
@@ -1,25 +0,0 @@
-
-# Aliases
-type Receiver = fn() -> any
-type Sender = fn(any)
-
-fn new_channel() -> (Sender, Receiver) {
- queue := []
-
- fn send(n: any) {
- queue.push(n) # mutate in-place
- }
-
- fn recv() -> any | nil {
- queue.pop()
- }
-
- (send, recv)
-}
-
-(send, recv) := new_channel()
-
-(
- send:,
- recv:,
-)
diff --git a/examples/worst.ang b/examples/worst.ang
deleted file mode 100644
index 47b90db..0000000
--- a/examples/worst.ang
+++ /dev/null
@@ -1,4 +0,0 @@
-import "worst.ang"
-
-write("Hello world!")
-
diff --git a/foo.ang b/foo.ang
deleted file mode 100644
index e69de29..0000000
diff --git a/go.work.sum b/go.work.sum
deleted file mode 100644
index 2d35219..0000000
--- a/go.work.sum
+++ /dev/null
@@ -1 +0,0 @@
-github.com/alecthomas/repr v0.5.2/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
diff --git a/lib/list.ang b/lib/list.ang
index 792751f..254912d 100644
--- a/lib/list.ang
+++ b/lib/list.ang
@@ -1,5 +1,5 @@
-fn map(list: [T], f: fn(T) -> R) -> [R] {
+fn ([T]) map(f: fn(T) -> R) -> [R] {
out := []
for v in list.iter() {
diff --git a/lib/math.ang b/lib/math.ang
index 9dac01a..120e60e 100644
--- a/lib/math.ang
+++ b/lib/math.ang
@@ -249,5 +249,3 @@ fn tan(x: float) -> float {
# todo
0.0
}
-
-(E:, PI:, sqrt:, log:, ln:, exp:, pow:)
diff --git a/lib/testing.ang b/lib/testing.ang
index 82e7b77..59aed2c 100644
--- a/lib/testing.ang
+++ b/lib/testing.ang
@@ -1,25 +1,25 @@
NAMESPACE := ""
-fn namespace(name: str, test: fn()) {
+func namespace(name: string, test: func()) {
NAMESPACE = name
test()
}
-fn eq(a: T, b: T) {
+func assertEqual(a: any, b: any) {
if a != b {
- println(format("assertion error: % should (but doesn't) equal %", [a, b]))
+ write(format("assertion error: % should (but doesn't) equal %", [a, b]))
exit(1)
} else if env("DEBUG") != "" {
- println(format("assertion success: % equals %", [a, b]))
+ write(format("assertion success: % equals %", [a, b]))
}
}
-fn neq(a: T, b: T) {
+func assertNotEqual(a: any, b: any) {
if a == b {
- println(format("assertion error: % shouldn't (but does) equal %", [a, b]))
+ write(format("assertion error: % shouldn't (but does) equal %", [a, b]))
exit(1)
} else if env("DEBUG") != "" {
- println(format("assertion success: % doesn't equal %", [a, b]))
+ write(format("assertion success: % doesn't equal %", [a, b]))
}
}
diff --git a/records.ang b/records.ang
deleted file mode 100644
index 198475c..0000000
--- a/records.ang
+++ /dev/null
@@ -1,29 +0,0 @@
-
-type User = (
- id: int,
- name: str,
-)
-
-
-user := {
- user_id := 0
- all_users := []User
-
- (
- get_all: fn() -> [User] { all_users },
- new: fn(name: str) -> User {
- data := (id: { user_id = user_id + 1 }, name:)
- all_users.append(data)
- data
- },
- fmt: fn(user: User) -> str {
- user.name + "(" + str(user.id) + ")"
- }
- )
-}
-
-abe := user.new("abe")
-lincoln := user.new("lincoln")
-
-println(abe)
-println(lincoln)
diff --git a/test_all.sh b/test_all.sh
index a6bdd01..9905f24 100755
--- a/test_all.sh
+++ b/test_all.sh
@@ -2,7 +2,7 @@
echo '=== Building WASM lib ==='
cd wasm || exit 1
-if ! GOOS=js GOARCH=wasm go build . "$@"; then
+if ! GOOS=js GOARCH=wasm go build .; then
echo "=x= Had error building WASM lib =x="
exit 1
else
@@ -12,7 +12,7 @@ cd ..
echo '=== Building CLI ==='
cd cli || exit 1
-if ! go build . "$@"; then
+if ! go build .; then
echo "=x= Had error building CLI =x="
exit 1
else
@@ -22,7 +22,7 @@ cd ..
echo "=== Running go core tests ==="
cd core || exit 1
-if ! go test . "$@"; then
+if ! go test .; then
echo "=x= Core testing failed =x= "
exit 1
else
diff --git a/tests/forp.ang b/tests/forp.ang
deleted file mode 100644
index 0891ab6..0000000
--- a/tests/forp.ang
+++ /dev/null
@@ -1,52 +0,0 @@
-
-fn range(from: int, to: int) -> (fn() -> (int, bool)) {
- i := from - 1
-
- fn() -> (int, bool) {
- i = i + 1
- if i >= to {
- (-1, false)
- } else {
- (i, true)
- }
- }
-}
-
-for i in range(0, 10) {
- println(i)
-}
-
-fn chars(s: str) -> (fn() -> (str, bool)) {
- i := 0
-
- fn() -> (str, bool) {
- if i >= s.length() {
- ("", false)
- } else {
- c := s[i]
- i = i + 1
-
- (c, true)
- }
- }
-}
-
-for c in chars("hello") {
- print(c)
- print(" ")
-}
-
-println("")
-
-fn items(l: [any]) -> (fn() -> (any, bool)) {
- i := 0
-
- fn() -> (any, bool) {
- if i >= l.length() {
- (nil, false)
- } else {
- i = i + 1
- (l[i - 1], true)
- }
- }
-}
diff --git a/tests/list.ang b/tests/list.ang
index e98fcf8..8554f14 100644
--- a/tests/list.ang
+++ b/tests/list.ang
@@ -34,10 +34,3 @@ assertEq("the, first, time".split(", "), ["the", "first", "time"])
# list indexing
assertEq([1, 2, 3].at(1), 2)
assertEq(["a", "b", "c"].at(2), "c")
-
-# mutating list
-a := [1, 2, 3]
-assertEq(a, [1, 2, 3])
-
-a[1] = 4
-assertEq(a, [1, 4, 3])
diff --git a/tests/tuple.ang b/tests/tuple.ang
index 65e99e9..81aa508 100644
--- a/tests/tuple.ang
+++ b/tests/tuple.ang
@@ -9,10 +9,3 @@ fn neighbours(n: int) -> (int, int) {
}
assertEq(neighbours(2), (1, 3))
-
-a := (1, 2)
-assertEq(a, (1, 2))
-
-(x, y) := a
-assertEq(x, 1)
-assertEq(y, 2)