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 83098d5..617871e 100644 --- a/core/compiler.go +++ b/core/compiler.go @@ -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) @@ -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/parser.go b/core/parser.go index ca360af..6462b7a 100644 --- a/core/parser.go +++ b/core/parser.go @@ -76,13 +76,9 @@ func (p ParsingError) Format() 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 @@ -94,9 +90,7 @@ func NewParser(source string, trace []string, tokens []Token) *Parser { source: source, trace: trace, tokens: tokens, - state: ParserState{ - pos: 0, - }, + pos: 0, } } @@ -122,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 } @@ -145,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 } @@ -171,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 { @@ -236,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) { @@ -263,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 @@ -294,7 +282,7 @@ func (p *Parser) expression(mustBeBlock bool) (Node, error) { sig, start, - p.state.prev.End, + p.prev.End, }, nil case TokenIf: @@ -312,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 } @@ -328,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 { @@ -338,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 { @@ -359,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 { @@ -391,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 @@ -404,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: @@ -420,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) @@ -521,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() @@ -536,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() @@ -570,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 @@ -589,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 @@ -604,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 { @@ -622,7 +610,7 @@ func (p *Parser) chain() (Node, error) { f, index, start, - p.state.prev.End, + p.prev.End, } } else { break @@ -633,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: @@ -706,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... @@ -720,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) { @@ -743,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 { @@ -766,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 { @@ -783,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 @@ -806,7 +794,7 @@ func (p *Parser) factor() (Node, error) { }, args, start, - p.state.prev.End, + p.prev.End, }, nil } @@ -818,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() @@ -854,7 +842,7 @@ func (p *Parser) factor() (Node, error) { yield, logic, start, - p.state.prev.End, + p.prev.End, } if name != nil { @@ -863,7 +851,7 @@ func (p *Parser) factor() (Node, error) { fn, true, start, - p.state.prev.End, + p.prev.End, }, nil } @@ -871,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) @@ -944,7 +876,6 @@ func (p *Parser) factor() (Node, error) { return nil, err } - p.state.ignoreNewLine = oldCare return v, nil } @@ -966,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) } } @@ -1026,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 } @@ -1047,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 } @@ -1075,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() @@ -1146,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 @@ -1200,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": @@ -1235,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/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 efb5f41..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,8 +47,8 @@ func (v ValueType) String() string { return "function" case BuiltinFunctionValueType: return "builtin function" - case RecordValueType: - return "record" + case VariableValueType: + return "variable" } return "undefined" @@ -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, } @@ -598,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, } } @@ -633,9 +635,13 @@ 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, } } @@ -655,7 +661,7 @@ func (v *TupleValue) Equals(other Value) bool { } var TuplePrototype = map[string]*BuiltinFunctionValue{ - "at": { + "at": &BuiltinFunctionValue{ "at", &FunctionSignature{ []TypeSignature{&IntegerSignature{}}, @@ -712,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, @@ -752,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, @@ -761,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 f07890f..17a1a62 100644 --- a/core/vm.go +++ b/core/vm.go @@ -126,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. @@ -139,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 @@ -152,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 ) @@ -272,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" } @@ -642,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 { @@ -982,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) @@ -990,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: @@ -1074,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() @@ -1094,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) @@ -1116,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) @@ -1128,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) @@ -1142,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 @@ -1300,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/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/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/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/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/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)