Compare commits
No commits in common. "575fd8e37ad071d613fa512e8713dcab1a90293c" and "5c336c7decbd0536a5bc5d719dbc634f05bec8c5" have entirely different histories.
575fd8e37a
...
5c336c7dec
33 changed files with 1975 additions and 1739 deletions
40
bad.ang
Normal file
40
bad.ang
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
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))
|
||||||
15
chars.ang
Normal file
15
chars.ang
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -150,8 +150,7 @@ func makeChunk(ctx *Context, fpath string, ignoreWarnings bool) (*core.Chunk, er
|
||||||
if ctx.Debug {
|
if ctx.Debug {
|
||||||
log.Println("Compiling parse tree")
|
log.Println("Compiling parse tree")
|
||||||
}
|
}
|
||||||
|
err = c.Compile(tree)
|
||||||
_, err = c.Compile(tree)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
var e core.FormatedError
|
var e core.FormatedError
|
||||||
if errors.As(err, &e) {
|
if errors.As(err, &e) {
|
||||||
|
|
@ -297,7 +296,7 @@ func (cmd *ReplCmd) Run(ctx *Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
c.SetSource(src)
|
c.SetSource(src)
|
||||||
if _, err = c.Compile(prog); err != nil {
|
if err = c.Compile(prog); err != nil {
|
||||||
var e core.FormatedError
|
var e core.FormatedError
|
||||||
if errors.As(err, &e) {
|
if errors.As(err, &e) {
|
||||||
log.Print(e.Format())
|
log.Print(e.Format())
|
||||||
|
|
|
||||||
24
codegen.ang
Normal file
24
codegen.ang
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
1417
core/compiler.go
1417
core/compiler.go
File diff suppressed because it is too large
Load diff
|
|
@ -7,29 +7,24 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Token struct {
|
type Token struct {
|
||||||
Type TokenKind
|
Type TokenType
|
||||||
Start Pos
|
Start Pos
|
||||||
End Pos
|
End Pos
|
||||||
Line Pos
|
Line Pos
|
||||||
Lexeme string
|
Lexeme string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Token) Bounds() (Pos, Pos) {
|
|
||||||
return t.Start, t.End
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t Token) String() string {
|
func (t Token) String() string {
|
||||||
return fmt.Sprintf("token %s, '%s' %d -> %d, line %d", t.Type.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
|
type TokenType uint64
|
||||||
|
|
||||||
const (
|
const (
|
||||||
TokenPlus TokenKind = iota
|
TokenPlus TokenType = iota
|
||||||
TokenMinus
|
TokenMinus
|
||||||
TokenStar
|
TokenStar
|
||||||
TokenSlash
|
TokenSlash
|
||||||
TokenPercent
|
|
||||||
TokenBang
|
TokenBang
|
||||||
TokenSemicolon
|
TokenSemicolon
|
||||||
|
|
||||||
|
|
@ -56,10 +51,7 @@ const (
|
||||||
TokenVar
|
TokenVar
|
||||||
TokenIf
|
TokenIf
|
||||||
TokenElse
|
TokenElse
|
||||||
TokenInclude
|
TokenImport
|
||||||
TokenType
|
|
||||||
TokenFor
|
|
||||||
TokenIn
|
|
||||||
|
|
||||||
TokenComma
|
TokenComma
|
||||||
TokenDot
|
TokenDot
|
||||||
|
|
@ -85,7 +77,7 @@ const (
|
||||||
TokenError
|
TokenError
|
||||||
)
|
)
|
||||||
|
|
||||||
func (t TokenKind) String() string {
|
func (t TokenType) String() string {
|
||||||
switch t {
|
switch t {
|
||||||
case TokenPlus:
|
case TokenPlus:
|
||||||
return "plus"
|
return "plus"
|
||||||
|
|
@ -167,8 +159,8 @@ func (t TokenKind) String() string {
|
||||||
return "open bracket"
|
return "open bracket"
|
||||||
case TokenCloseBracket:
|
case TokenCloseBracket:
|
||||||
return "close bracket"
|
return "close bracket"
|
||||||
case TokenInclude:
|
case TokenImport:
|
||||||
return "include"
|
return "import"
|
||||||
case TokenColon:
|
case TokenColon:
|
||||||
return "colon"
|
return "colon"
|
||||||
case TokenPipe:
|
case TokenPipe:
|
||||||
|
|
@ -179,34 +171,11 @@ func (t TokenKind) String() string {
|
||||||
return "arrow"
|
return "arrow"
|
||||||
case TokenNewLine:
|
case TokenNewLine:
|
||||||
return "newline"
|
return "newline"
|
||||||
case TokenType:
|
|
||||||
return "type"
|
|
||||||
case TokenFor:
|
|
||||||
return "for"
|
|
||||||
case TokenIn:
|
|
||||||
return "in"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
panic("UNDEFINED TOKENTYPE STRING CONVERSION")
|
panic("UNDEFINED TOKENTYPE STRING CONVERSION")
|
||||||
}
|
}
|
||||||
|
|
||||||
var Keywords = map[string]TokenKind{
|
|
||||||
"true": TokenTrue,
|
|
||||||
"false": TokenFalse,
|
|
||||||
"nil": TokenNil,
|
|
||||||
"if": TokenIf,
|
|
||||||
"else": TokenElse,
|
|
||||||
"include": TokenInclude,
|
|
||||||
"var": TokenVar,
|
|
||||||
"fn": TokenFunc,
|
|
||||||
"return": TokenReturn,
|
|
||||||
"while": TokenWhile,
|
|
||||||
"breakpoint": TokenBreakpoint,
|
|
||||||
"type": TokenType,
|
|
||||||
"for": TokenFor,
|
|
||||||
"in": TokenIn,
|
|
||||||
}
|
|
||||||
|
|
||||||
type Lexer struct {
|
type Lexer struct {
|
||||||
src []rune
|
src []rune
|
||||||
start Pos
|
start Pos
|
||||||
|
|
@ -269,8 +238,6 @@ func (l *Lexer) NextToken() (Token, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return l.makeToken(TokenSlash), nil
|
return l.makeToken(TokenSlash), nil
|
||||||
case '%':
|
|
||||||
return l.makeToken(TokenPercent), nil
|
|
||||||
case '(':
|
case '(':
|
||||||
return l.makeToken(TokenOpenParenthesis), nil
|
return l.makeToken(TokenOpenParenthesis), nil
|
||||||
case ')':
|
case ')':
|
||||||
|
|
@ -373,12 +340,32 @@ func (l *Lexer) NextToken() (Token, error) {
|
||||||
l.advance()
|
l.advance()
|
||||||
}
|
}
|
||||||
|
|
||||||
lexeme := string(l.src[l.start:l.current])
|
switch string(l.src[l.start:l.current]) {
|
||||||
if k, ok := Keywords[lexeme]; ok {
|
case "true":
|
||||||
return l.makeToken(k), nil
|
return l.makeToken(TokenTrue), nil
|
||||||
}
|
case "false":
|
||||||
|
return l.makeToken(TokenFalse), nil
|
||||||
|
case "nil":
|
||||||
|
return l.makeToken(TokenNil), nil
|
||||||
|
case "if":
|
||||||
|
return l.makeToken(TokenIf), nil
|
||||||
|
case "else":
|
||||||
|
return l.makeToken(TokenElse), nil
|
||||||
|
case "var":
|
||||||
|
return l.makeToken(TokenVar), nil
|
||||||
|
case "fn":
|
||||||
|
return l.makeToken(TokenFunc), nil
|
||||||
|
case "while":
|
||||||
|
return l.makeToken(TokenWhile), nil
|
||||||
|
case "breakpoint":
|
||||||
|
return l.makeToken(TokenBreakpoint), nil
|
||||||
|
case "return":
|
||||||
|
return l.makeToken(TokenReturn), nil
|
||||||
|
case "import":
|
||||||
|
return l.makeToken(TokenImport), nil
|
||||||
|
default:
|
||||||
return l.makeToken(TokenName), nil
|
return l.makeToken(TokenName), nil
|
||||||
|
}
|
||||||
} else if c == '0' && l.peek() != '.' {
|
} else if c == '0' && l.peek() != '.' {
|
||||||
if l.peek() == 'x' {
|
if l.peek() == 'x' {
|
||||||
l.advance()
|
l.advance()
|
||||||
|
|
@ -413,7 +400,7 @@ func (l *Lexer) NextToken() (Token, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewToken(t TokenKind, start Pos, end Pos, line Pos, lexeme string) Token {
|
func NewToken(t TokenType, start Pos, end Pos, line Pos, lexeme string) Token {
|
||||||
return Token{
|
return Token{
|
||||||
Type: t,
|
Type: t,
|
||||||
Start: start,
|
Start: start,
|
||||||
|
|
@ -438,7 +425,7 @@ func (l *Lexer) Tokenize() ([]Token, error) {
|
||||||
return tokens, err
|
return tokens, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Lexer) makeToken(t TokenKind) Token {
|
func (l *Lexer) makeToken(t TokenType) Token {
|
||||||
return NewToken(t, l.start, l.current, l.line, string(l.src[l.start:l.current]))
|
return NewToken(t, l.start, l.current, l.line, string(l.src[l.start:l.current]))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,37 +6,37 @@ import (
|
||||||
|
|
||||||
type LexerTestData struct {
|
type LexerTestData struct {
|
||||||
source string
|
source string
|
||||||
expectedTokens []TokenKind
|
expectedTokens []TokenType
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetLexerTestData() map[string]LexerTestData {
|
func GetLexerTestData() map[string]LexerTestData {
|
||||||
return map[string]LexerTestData{
|
return map[string]LexerTestData{
|
||||||
"hello_world_string(1)": {
|
"hello_world_string(1)": {
|
||||||
"\"Hello world\"",
|
"\"Hello world\"",
|
||||||
[]TokenKind{TokenString, TokenEOF},
|
[]TokenType{TokenString, TokenEOF},
|
||||||
},
|
},
|
||||||
"empty_string(1)": {
|
"empty_string(1)": {
|
||||||
"\"\"",
|
"\"\"",
|
||||||
[]TokenKind{TokenString, TokenEOF},
|
[]TokenType{TokenString, TokenEOF},
|
||||||
},
|
},
|
||||||
"simple number(1)": {
|
"simple number(1)": {
|
||||||
"1024",
|
"1024",
|
||||||
[]TokenKind{TokenInteger, TokenEOF},
|
[]TokenType{TokenInteger, TokenEOF},
|
||||||
},
|
},
|
||||||
"simple_arithmetics(7)": {
|
"simple_arithmetics(7)": {
|
||||||
"1 + 23 / 4 * 3",
|
"1 + 23 / 4 * 3",
|
||||||
[]TokenKind{
|
[]TokenType{
|
||||||
TokenInteger, TokenPlus, TokenInteger, TokenSlash,
|
TokenInteger, TokenPlus, TokenInteger, TokenSlash,
|
||||||
TokenInteger, TokenStar, TokenInteger, TokenEOF,
|
TokenInteger, TokenStar, TokenInteger, TokenEOF,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"condition(3)": {
|
"condition(3)": {
|
||||||
"a <= 200",
|
"a <= 200",
|
||||||
[]TokenKind{TokenName, TokenLessThanOrEqual, TokenInteger, TokenEOF},
|
[]TokenType{TokenName, TokenLessThanOrEqual, TokenInteger, TokenEOF},
|
||||||
},
|
},
|
||||||
"if_statement(10)": {
|
"if_statement(10)": {
|
||||||
"if a >= 200 {\n write(\"Hello world!\")\n}",
|
"if a >= 200 {\n write(\"Hello world!\")\n}",
|
||||||
[]TokenKind{
|
[]TokenType{
|
||||||
TokenIf, TokenName, TokenGreaterThanOrEqual, TokenInteger, TokenOpenBrace, TokenNewLine,
|
TokenIf, TokenName, TokenGreaterThanOrEqual, TokenInteger, TokenOpenBrace, TokenNewLine,
|
||||||
TokenName, TokenOpenParenthesis, TokenString, TokenCloseParenthesis, TokenNewLine,
|
TokenName, TokenOpenParenthesis, TokenString, TokenCloseParenthesis, TokenNewLine,
|
||||||
TokenCloseBrace, TokenEOF,
|
TokenCloseBrace, TokenEOF,
|
||||||
|
|
@ -44,7 +44,7 @@ func GetLexerTestData() map[string]LexerTestData {
|
||||||
},
|
},
|
||||||
"if_else_statement(20)": {
|
"if_else_statement(20)": {
|
||||||
"if 23 * 2/3 > 32 {\n write(\"It is larger!\")\n} else {\n write(\"It is lower!\")\n}",
|
"if 23 * 2/3 > 32 {\n write(\"It is larger!\")\n} else {\n write(\"It is lower!\")\n}",
|
||||||
[]TokenKind{
|
[]TokenType{
|
||||||
TokenIf, TokenInteger, TokenStar, TokenInteger, TokenSlash, TokenInteger, TokenGreaterThan, TokenInteger, TokenOpenBrace, TokenNewLine,
|
TokenIf, TokenInteger, TokenStar, TokenInteger, TokenSlash, TokenInteger, TokenGreaterThan, TokenInteger, TokenOpenBrace, TokenNewLine,
|
||||||
TokenName, TokenOpenParenthesis, TokenString, TokenCloseParenthesis, TokenNewLine, TokenCloseBrace,
|
TokenName, TokenOpenParenthesis, TokenString, TokenCloseParenthesis, TokenNewLine, TokenCloseBrace,
|
||||||
TokenElse, TokenOpenBrace, TokenNewLine, TokenName, TokenOpenParenthesis, TokenString, TokenCloseParenthesis, TokenNewLine, TokenCloseBrace,
|
TokenElse, TokenOpenBrace, TokenNewLine, TokenName, TokenOpenParenthesis, TokenString, TokenCloseParenthesis, TokenNewLine, TokenCloseBrace,
|
||||||
|
|
@ -53,11 +53,11 @@ func GetLexerTestData() map[string]LexerTestData {
|
||||||
},
|
},
|
||||||
"empty_string": {
|
"empty_string": {
|
||||||
"",
|
"",
|
||||||
[]TokenKind{TokenEOF},
|
[]TokenType{TokenEOF},
|
||||||
},
|
},
|
||||||
"full_arithmetic_equality": {
|
"full_arithmetic_equality": {
|
||||||
"a + 2 == 10 * 2 / 3",
|
"a + 2 == 10 * 2 / 3",
|
||||||
[]TokenKind{
|
[]TokenType{
|
||||||
TokenName, TokenPlus, TokenInteger, TokenEquals,
|
TokenName, TokenPlus, TokenInteger, TokenEquals,
|
||||||
TokenInteger, TokenStar, TokenInteger, TokenSlash, TokenInteger,
|
TokenInteger, TokenStar, TokenInteger, TokenSlash, TokenInteger,
|
||||||
TokenEOF,
|
TokenEOF,
|
||||||
|
|
@ -65,11 +65,11 @@ func GetLexerTestData() map[string]LexerTestData {
|
||||||
},
|
},
|
||||||
"name": {
|
"name": {
|
||||||
"print",
|
"print",
|
||||||
[]TokenKind{TokenName, TokenEOF},
|
[]TokenType{TokenName, TokenEOF},
|
||||||
},
|
},
|
||||||
"bunch_of_parentheses": {
|
"bunch_of_parentheses": {
|
||||||
"(((())))",
|
"(((())))",
|
||||||
[]TokenKind{
|
[]TokenType{
|
||||||
TokenOpenParenthesis, TokenOpenParenthesis, TokenOpenParenthesis, TokenOpenParenthesis,
|
TokenOpenParenthesis, TokenOpenParenthesis, TokenOpenParenthesis, TokenOpenParenthesis,
|
||||||
TokenCloseParenthesis, TokenCloseParenthesis, TokenCloseParenthesis, TokenCloseParenthesis,
|
TokenCloseParenthesis, TokenCloseParenthesis, TokenCloseParenthesis, TokenCloseParenthesis,
|
||||||
TokenEOF,
|
TokenEOF,
|
||||||
|
|
@ -77,22 +77,22 @@ func GetLexerTestData() map[string]LexerTestData {
|
||||||
},
|
},
|
||||||
"space_before_string": {
|
"space_before_string": {
|
||||||
"\n \"\"",
|
"\n \"\"",
|
||||||
[]TokenKind{TokenNewLine, TokenString, TokenEOF},
|
[]TokenType{TokenNewLine, TokenString, TokenEOF},
|
||||||
},
|
},
|
||||||
"write_call": {
|
"write_call": {
|
||||||
"write(\"Hello world\")",
|
"write(\"Hello world\")",
|
||||||
[]TokenKind{TokenName, TokenOpenParenthesis, TokenString, TokenCloseParenthesis, TokenEOF},
|
[]TokenType{TokenName, TokenOpenParenthesis, TokenString, TokenCloseParenthesis, TokenEOF},
|
||||||
},
|
},
|
||||||
"complex_comparison": {
|
"complex_comparison": {
|
||||||
"!(h__elo123 >= 1)",
|
"!(h__elo123 >= 1)",
|
||||||
[]TokenKind{
|
[]TokenType{
|
||||||
TokenBang, TokenOpenParenthesis, TokenName, TokenGreaterThanOrEqual, TokenInteger, TokenCloseParenthesis,
|
TokenBang, TokenOpenParenthesis, TokenName, TokenGreaterThanOrEqual, TokenInteger, TokenCloseParenthesis,
|
||||||
TokenEOF,
|
TokenEOF,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"3assignments_1condition": {
|
"3assignments_1condition": {
|
||||||
"a = 8 * 32\nb = a > 256\nc = a <= 256\n!b == c",
|
"a = 8 * 32\nb = a > 256\nc = a <= 256\n!b == c",
|
||||||
[]TokenKind{
|
[]TokenType{
|
||||||
TokenName, TokenAssign, TokenInteger, TokenStar, TokenInteger, TokenNewLine,
|
TokenName, TokenAssign, TokenInteger, TokenStar, TokenInteger, TokenNewLine,
|
||||||
TokenName, TokenAssign, TokenName, TokenGreaterThan, TokenInteger, TokenNewLine,
|
TokenName, TokenAssign, TokenName, TokenGreaterThan, TokenInteger, TokenNewLine,
|
||||||
TokenName, TokenAssign, TokenName, TokenLessThanOrEqual, TokenInteger, TokenNewLine,
|
TokenName, TokenAssign, TokenName, TokenLessThanOrEqual, TokenInteger, TokenNewLine,
|
||||||
|
|
@ -101,14 +101,14 @@ func GetLexerTestData() map[string]LexerTestData {
|
||||||
},
|
},
|
||||||
"function": {
|
"function": {
|
||||||
"fn sum(a, b) {\n return a + b\n}",
|
"fn sum(a, b) {\n return a + b\n}",
|
||||||
[]TokenKind{
|
[]TokenType{
|
||||||
TokenFunc, TokenName, TokenOpenParenthesis, TokenName, TokenComma, TokenName, TokenCloseParenthesis,
|
TokenFunc, TokenName, TokenOpenParenthesis, TokenName, TokenComma, TokenName, TokenCloseParenthesis,
|
||||||
TokenOpenBrace, TokenNewLine, TokenReturn, TokenName, TokenPlus, TokenName, TokenNewLine, TokenCloseBrace,
|
TokenOpenBrace, TokenNewLine, TokenReturn, TokenName, TokenPlus, TokenName, TokenNewLine, TokenCloseBrace,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"while_loop": {
|
"while_loop": {
|
||||||
"while a < 5 {\n a = a + 1\n}",
|
"while a < 5 {\n a = a + 1\n}",
|
||||||
[]TokenKind{
|
[]TokenType{
|
||||||
TokenWhile, TokenName, TokenLessThan, TokenInteger, TokenOpenBrace, TokenNewLine,
|
TokenWhile, TokenName, TokenLessThan, TokenInteger, TokenOpenBrace, TokenNewLine,
|
||||||
TokenName, TokenAssign, TokenName, TokenPlus, TokenInteger, TokenNewLine, TokenCloseBrace, TokenEOF,
|
TokenName, TokenAssign, TokenName, TokenPlus, TokenInteger, TokenNewLine, TokenCloseBrace, TokenEOF,
|
||||||
},
|
},
|
||||||
|
|
@ -117,14 +117,14 @@ func GetLexerTestData() map[string]LexerTestData {
|
||||||
"sum := fn(a, b) {\n" +
|
"sum := fn(a, b) {\n" +
|
||||||
" return a + b\n" +
|
" return a + b\n" +
|
||||||
"}",
|
"}",
|
||||||
[]TokenKind{
|
[]TokenType{
|
||||||
TokenName, TokenDeclare, TokenFunc, TokenOpenParenthesis, TokenName, TokenComma, TokenName, TokenCloseParenthesis,
|
TokenName, TokenDeclare, TokenFunc, TokenOpenParenthesis, TokenName, TokenComma, TokenName, TokenCloseParenthesis,
|
||||||
TokenOpenBrace, TokenNewLine, TokenReturn, TokenName, TokenPlus, TokenName, TokenNewLine, TokenCloseBrace,
|
TokenOpenBrace, TokenNewLine, TokenReturn, TokenName, TokenPlus, TokenName, TokenNewLine, TokenCloseBrace,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"list": {
|
"list": {
|
||||||
"data := [3, 1, 4, 1]",
|
"data := [3, 1, 4, 1]",
|
||||||
[]TokenKind{
|
[]TokenType{
|
||||||
TokenName, TokenDeclare, TokenOpenBracket, TokenInteger, TokenComma, TokenInteger, TokenComma, TokenInteger, TokenComma, TokenInteger, TokenCloseBracket,
|
TokenName, TokenDeclare, TokenOpenBracket, TokenInteger, TokenComma, TokenInteger, TokenComma, TokenInteger, TokenComma, TokenInteger, TokenCloseBracket,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
134
core/nodes.go
134
core/nodes.go
|
|
@ -16,7 +16,7 @@ type Node interface {
|
||||||
Bounds() (Pos, Pos)
|
Bounds() (Pos, Pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Bounded interface {
|
type Boundary interface {
|
||||||
Bounds() (Pos, Pos)
|
Bounds() (Pos, Pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -34,16 +34,12 @@ const (
|
||||||
BlockNodeType
|
BlockNodeType
|
||||||
ConditionalNodeType
|
ConditionalNodeType
|
||||||
LoopNodeType
|
LoopNodeType
|
||||||
ForNodeType
|
|
||||||
AssignNodeType
|
AssignNodeType
|
||||||
InvokeNodeType
|
InvokeNodeType
|
||||||
CallNodeType
|
CallNodeType
|
||||||
FunctionNodeType
|
FunctionNodeType
|
||||||
ReturnNodeType
|
ReturnNodeType
|
||||||
AccessNodeType
|
AccessNodeType
|
||||||
AliasNodeType
|
|
||||||
IndexNodeType
|
|
||||||
IncludeNodeType
|
|
||||||
BreakpointNodeType
|
BreakpointNodeType
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -72,7 +68,7 @@ func (n NodeType) String() string {
|
||||||
case AssignNodeType:
|
case AssignNodeType:
|
||||||
return "Assign"
|
return "Assign"
|
||||||
case InvokeNodeType:
|
case InvokeNodeType:
|
||||||
return "Invoke"
|
return "Call"
|
||||||
case FunctionNodeType:
|
case FunctionNodeType:
|
||||||
return "Function"
|
return "Function"
|
||||||
case ReturnNodeType:
|
case ReturnNodeType:
|
||||||
|
|
@ -89,10 +85,6 @@ func (n NodeType) String() string {
|
||||||
return "Unary"
|
return "Unary"
|
||||||
case CallNodeType:
|
case CallNodeType:
|
||||||
return "Call"
|
return "Call"
|
||||||
case AliasNodeType:
|
|
||||||
return "Alias"
|
|
||||||
case IndexNodeType:
|
|
||||||
return "Index"
|
|
||||||
}
|
}
|
||||||
return "Invalid Node Type"
|
return "Invalid Node Type"
|
||||||
}
|
}
|
||||||
|
|
@ -239,7 +231,7 @@ func (n TupleNode) Bounds() (Pos, Pos) {
|
||||||
|
|
||||||
type AccessNode struct {
|
type AccessNode struct {
|
||||||
source Node
|
source Node
|
||||||
property *Token
|
property string
|
||||||
|
|
||||||
start Pos
|
start Pos
|
||||||
end Pos
|
end Pos
|
||||||
|
|
@ -250,7 +242,7 @@ func (n AccessNode) Type() NodeType {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n AccessNode) String() string {
|
func (n AccessNode) String() string {
|
||||||
return fmt.Sprintf("(%s from %s)", n.property.Lexeme, n.source)
|
return fmt.Sprintf("(%s from %s)", n.property, n.source)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n AccessNode) Bounds() (Pos, Pos) {
|
func (n AccessNode) Bounds() (Pos, Pos) {
|
||||||
|
|
@ -281,9 +273,9 @@ func (n BinaryOperation) String() string {
|
||||||
return "less or equal"
|
return "less or equal"
|
||||||
case BinaryGreaterEqual:
|
case BinaryGreaterEqual:
|
||||||
return "greater or equal"
|
return "greater or equal"
|
||||||
case BinaryBooleanAnd:
|
case BinaryAnd:
|
||||||
return "and"
|
return "and"
|
||||||
case BinaryBooleanOr:
|
case BinaryOr:
|
||||||
return "or"
|
return "or"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -295,10 +287,9 @@ const (
|
||||||
BinarySubtraction
|
BinarySubtraction
|
||||||
BinaryMultiplication
|
BinaryMultiplication
|
||||||
BinaryDivision
|
BinaryDivision
|
||||||
BinaryModulo
|
|
||||||
|
|
||||||
BinaryBooleanAnd
|
BinaryAnd
|
||||||
BinaryBooleanOr
|
BinaryOr
|
||||||
|
|
||||||
// Comparison
|
// Comparison
|
||||||
BinaryEquality
|
BinaryEquality
|
||||||
|
|
@ -319,8 +310,6 @@ func (n BinaryOperation) Symbol() string {
|
||||||
return "*"
|
return "*"
|
||||||
case BinaryDivision:
|
case BinaryDivision:
|
||||||
return "/"
|
return "/"
|
||||||
case BinaryModulo:
|
|
||||||
return "%"
|
|
||||||
case BinaryEquality:
|
case BinaryEquality:
|
||||||
return "=="
|
return "=="
|
||||||
case BinaryInequality:
|
case BinaryInequality:
|
||||||
|
|
@ -333,9 +322,9 @@ func (n BinaryOperation) Symbol() string {
|
||||||
return "<="
|
return "<="
|
||||||
case BinaryGreaterEqual:
|
case BinaryGreaterEqual:
|
||||||
return ">="
|
return ">="
|
||||||
case BinaryBooleanAnd:
|
case BinaryAnd:
|
||||||
return "&&"
|
return "&&"
|
||||||
case BinaryBooleanOr:
|
case BinaryOr:
|
||||||
return "||"
|
return "||"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -348,7 +337,6 @@ type BinaryNode struct {
|
||||||
Left Node
|
Left Node
|
||||||
Right Node
|
Right Node
|
||||||
|
|
||||||
operator *Token
|
|
||||||
start Pos
|
start Pos
|
||||||
end Pos
|
end Pos
|
||||||
}
|
}
|
||||||
|
|
@ -398,7 +386,6 @@ type UnaryNode struct {
|
||||||
UnaryOperation
|
UnaryOperation
|
||||||
value Node
|
value Node
|
||||||
|
|
||||||
operator *Token
|
|
||||||
start Pos
|
start Pos
|
||||||
end Pos
|
end Pos
|
||||||
}
|
}
|
||||||
|
|
@ -417,7 +404,7 @@ func (n UnaryNode) Bounds() (Pos, Pos) {
|
||||||
|
|
||||||
// BooleanNode boolean value
|
// BooleanNode boolean value
|
||||||
type BooleanNode struct {
|
type BooleanNode struct {
|
||||||
Boolean bool
|
value bool
|
||||||
|
|
||||||
start Pos
|
start Pos
|
||||||
end Pos
|
end Pos
|
||||||
|
|
@ -428,7 +415,7 @@ func (n BooleanNode) Type() NodeType {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n BooleanNode) String() string {
|
func (n BooleanNode) String() string {
|
||||||
return strconv.FormatBool(n.Boolean)
|
return strconv.FormatBool(n.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n BooleanNode) Bounds() (Pos, Pos) {
|
func (n BooleanNode) Bounds() (Pos, Pos) {
|
||||||
|
|
@ -506,7 +493,7 @@ func (n ConditionalNode) Bounds() (Pos, Pos) {
|
||||||
return n.start, n.end
|
return n.start, n.end
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoopNode While loops
|
// LoopNode Loops (for/while)
|
||||||
type LoopNode struct {
|
type LoopNode struct {
|
||||||
condition Node
|
condition Node
|
||||||
do Node
|
do Node
|
||||||
|
|
@ -527,28 +514,6 @@ func (n LoopNode) Bounds() (Pos, Pos) {
|
||||||
return n.start, n.end
|
return n.start, n.end
|
||||||
}
|
}
|
||||||
|
|
||||||
// ForNode For loops
|
|
||||||
type ForNode struct {
|
|
||||||
counter Node
|
|
||||||
iterator Node
|
|
||||||
logic Node
|
|
||||||
|
|
||||||
start Pos
|
|
||||||
end Pos
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n ForNode) Type() NodeType {
|
|
||||||
return ForNodeType
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n ForNode) String() string {
|
|
||||||
return fmt.Sprintf("for %s in %s; %s", n.counter, n.iterator, n.logic)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n ForNode) Bounds() (Pos, Pos) {
|
|
||||||
return n.start, n.end
|
|
||||||
}
|
|
||||||
|
|
||||||
// AssignNode assignment
|
// AssignNode assignment
|
||||||
type AssignNode struct {
|
type AssignNode struct {
|
||||||
dest Node
|
dest Node
|
||||||
|
|
@ -595,7 +560,7 @@ func (n InvokeNode) Bounds() (Pos, Pos) {
|
||||||
// CallNode call a function of a value
|
// CallNode call a function of a value
|
||||||
type CallNode struct {
|
type CallNode struct {
|
||||||
source Node
|
source Node
|
||||||
name *Token
|
name Token
|
||||||
args []Node
|
args []Node
|
||||||
|
|
||||||
start Pos
|
start Pos
|
||||||
|
|
@ -642,18 +607,6 @@ func (n FunctionNode) Bounds() (Pos, Pos) {
|
||||||
return n.start, n.end
|
return n.start, n.end
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n FunctionNode) Signature() *FunctionSignature {
|
|
||||||
args := make([]TypeSignature, len(n.parameters))
|
|
||||||
for i, p := range n.parameters {
|
|
||||||
args[i] = p.Signature
|
|
||||||
}
|
|
||||||
|
|
||||||
return &FunctionSignature{
|
|
||||||
args,
|
|
||||||
n.yield,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReturnNode return a value out of this context
|
// ReturnNode return a value out of this context
|
||||||
type ReturnNode struct {
|
type ReturnNode struct {
|
||||||
value Node
|
value Node
|
||||||
|
|
@ -674,65 +627,6 @@ func (n ReturnNode) Bounds() (Pos, Pos) {
|
||||||
return n.start, n.end
|
return n.start, n.end
|
||||||
}
|
}
|
||||||
|
|
||||||
type AliasNode struct {
|
|
||||||
name *Token
|
|
||||||
signature TypeSignature
|
|
||||||
|
|
||||||
start Pos
|
|
||||||
end Pos
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n AliasNode) Type() NodeType {
|
|
||||||
return AliasNodeType
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n AliasNode) String() string {
|
|
||||||
return fmt.Sprintf("alias %s to be %s", n.name, n.signature)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n AliasNode) Bounds() (Pos, Pos) {
|
|
||||||
return n.start, n.end
|
|
||||||
}
|
|
||||||
|
|
||||||
type IncludeNode struct {
|
|
||||||
path *StringNode
|
|
||||||
|
|
||||||
start Pos
|
|
||||||
end Pos
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n IncludeNode) Type() NodeType {
|
|
||||||
return IncludeNodeType
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n IncludeNode) String() string {
|
|
||||||
return fmt.Sprintf("include \"%s\"", n.path)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n IncludeNode) Bounds() (Pos, Pos) {
|
|
||||||
return n.start, n.end
|
|
||||||
}
|
|
||||||
|
|
||||||
type IndexNode struct {
|
|
||||||
source Node
|
|
||||||
index Node
|
|
||||||
|
|
||||||
start Pos
|
|
||||||
end Pos
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n IndexNode) Type() NodeType {
|
|
||||||
return IndexNodeType
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n IndexNode) String() string {
|
|
||||||
return fmt.Sprintf("index %s of %s", n.source.String(), n.index)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n IndexNode) Bounds() (Pos, Pos) {
|
|
||||||
return n.start, n.end
|
|
||||||
}
|
|
||||||
|
|
||||||
type BreakpointNode struct {
|
type BreakpointNode struct {
|
||||||
start Pos
|
start Pos
|
||||||
end Pos
|
end Pos
|
||||||
|
|
|
||||||
823
core/parser.go
823
core/parser.go
File diff suppressed because it is too large
Load diff
|
|
@ -1,8 +1,9 @@
|
||||||
package core
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math/big"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -73,7 +74,6 @@ func GetTokenTestData() map[string]TokenTestData {
|
||||||
2,
|
2,
|
||||||
0, 0,
|
0, 0,
|
||||||
},
|
},
|
||||||
nil,
|
|
||||||
0, 0,
|
0, 0,
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
|
|
@ -129,7 +129,6 @@ func GetTokenTestData() map[string]TokenTestData {
|
||||||
"b",
|
"b",
|
||||||
0, 0,
|
0, 0,
|
||||||
},
|
},
|
||||||
nil,
|
|
||||||
0, 0,
|
0, 0,
|
||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
|
|
@ -191,14 +190,12 @@ func GetTokenTestData() map[string]TokenTestData {
|
||||||
1,
|
1,
|
||||||
0, 0,
|
0, 0,
|
||||||
},
|
},
|
||||||
nil,
|
|
||||||
0, 0,
|
0, 0,
|
||||||
},
|
},
|
||||||
&FloatNode{
|
&FloatNode{
|
||||||
5,
|
5,
|
||||||
0, 0,
|
0, 0,
|
||||||
},
|
},
|
||||||
nil,
|
|
||||||
0, 0,
|
0, 0,
|
||||||
},
|
},
|
||||||
&BinaryNode{
|
&BinaryNode{
|
||||||
|
|
@ -217,13 +214,10 @@ func GetTokenTestData() map[string]TokenTestData {
|
||||||
2,
|
2,
|
||||||
0, 0,
|
0, 0,
|
||||||
},
|
},
|
||||||
nil,
|
|
||||||
0, 0,
|
0, 0,
|
||||||
},
|
},
|
||||||
nil,
|
|
||||||
0, 0,
|
0, 0,
|
||||||
},
|
},
|
||||||
nil,
|
|
||||||
0, 0,
|
0, 0,
|
||||||
},
|
},
|
||||||
&BinaryNode{
|
&BinaryNode{
|
||||||
|
|
@ -236,10 +230,8 @@ func GetTokenTestData() map[string]TokenTestData {
|
||||||
2,
|
2,
|
||||||
0, 0,
|
0, 0,
|
||||||
},
|
},
|
||||||
nil,
|
|
||||||
0, 0,
|
0, 0,
|
||||||
},
|
},
|
||||||
nil,
|
|
||||||
0, 0,
|
0, 0,
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
|
|
@ -272,7 +264,6 @@ func GetTokenTestData() map[string]TokenTestData {
|
||||||
15,
|
15,
|
||||||
0, 0,
|
0, 0,
|
||||||
},
|
},
|
||||||
nil,
|
|
||||||
0, 0,
|
0, 0,
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
|
|
@ -308,7 +299,6 @@ func GetTokenTestData() map[string]TokenTestData {
|
||||||
0,
|
0,
|
||||||
0, 0,
|
0, 0,
|
||||||
},
|
},
|
||||||
nil,
|
|
||||||
0, 0,
|
0, 0,
|
||||||
},
|
},
|
||||||
do: &BlockNode{
|
do: &BlockNode{
|
||||||
|
|
@ -362,7 +352,6 @@ func GetTokenTestData() map[string]TokenTestData {
|
||||||
0,
|
0,
|
||||||
0, 0,
|
0, 0,
|
||||||
},
|
},
|
||||||
nil,
|
|
||||||
0, 0,
|
0, 0,
|
||||||
},
|
},
|
||||||
do: &BlockNode{
|
do: &BlockNode{
|
||||||
|
|
@ -470,7 +459,6 @@ func GetTokenTestData() map[string]TokenTestData {
|
||||||
"b",
|
"b",
|
||||||
0, 0,
|
0, 0,
|
||||||
},
|
},
|
||||||
nil,
|
|
||||||
0, 0,
|
0, 0,
|
||||||
},
|
},
|
||||||
0, 0,
|
0, 0,
|
||||||
|
|
@ -542,7 +530,6 @@ func GetTokenTestData() map[string]TokenTestData {
|
||||||
"b",
|
"b",
|
||||||
0, 0,
|
0, 0,
|
||||||
},
|
},
|
||||||
nil,
|
|
||||||
0, 0,
|
0, 0,
|
||||||
},
|
},
|
||||||
0, 0,
|
0, 0,
|
||||||
|
|
@ -578,7 +565,7 @@ func GetTokenTestData() map[string]TokenTestData {
|
||||||
"a",
|
"a",
|
||||||
0, 0,
|
0, 0,
|
||||||
},
|
},
|
||||||
&Token{TokenName, 0, 1, 0, "b"},
|
"b",
|
||||||
0, 0,
|
0, 0,
|
||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
|
|
@ -664,57 +651,6 @@ func GetTokenTestData() map[string]TokenTestData {
|
||||||
0, 0,
|
0, 0,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"single_tuple": {
|
|
||||||
[]Token{
|
|
||||||
NewToken(TokenOpenParenthesis, 0, 0, 0, "("),
|
|
||||||
NewToken(TokenInteger, 0, 0, 0, "1"),
|
|
||||||
NewToken(TokenComma, 0, 0, 0, ","),
|
|
||||||
NewToken(TokenCloseParenthesis, 0, 0, 0, ")"),
|
|
||||||
NewToken(TokenEOF, 0, 0, 0, ""),
|
|
||||||
},
|
|
||||||
&BlockNode{
|
|
||||||
[]Node{
|
|
||||||
&TupleNode{
|
|
||||||
[]Node{
|
|
||||||
&IntegerNode{
|
|
||||||
big.NewInt(1),
|
|
||||||
0, 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
0, 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
0, 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"tuple": {
|
|
||||||
[]Token{
|
|
||||||
NewToken(TokenOpenParenthesis, 0, 0, 0, "("),
|
|
||||||
NewToken(TokenInteger, 0, 0, 0, "1"),
|
|
||||||
NewToken(TokenComma, 0, 0, 0, ","),
|
|
||||||
NewToken(TokenInteger, 0, 0, 0, "2"),
|
|
||||||
NewToken(TokenCloseParenthesis, 0, 0, 0, ")"),
|
|
||||||
NewToken(TokenEOF, 0, 0, 0, ""),
|
|
||||||
},
|
|
||||||
&BlockNode{
|
|
||||||
[]Node{
|
|
||||||
&TupleNode{
|
|
||||||
[]Node{
|
|
||||||
&IntegerNode{
|
|
||||||
big.NewInt(1),
|
|
||||||
0, 0,
|
|
||||||
},
|
|
||||||
&IntegerNode{
|
|
||||||
big.NewInt(2),
|
|
||||||
0, 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
0, 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
0, 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -781,10 +717,10 @@ func NodeEquality(t *testing.T, n1 Node, n2 Node) {
|
||||||
NodeEquality(t, n1.(*BinaryNode).Right, n2.(*BinaryNode).Right)
|
NodeEquality(t, n1.(*BinaryNode).Right, n2.(*BinaryNode).Right)
|
||||||
|
|
||||||
case BooleanNodeType:
|
case BooleanNodeType:
|
||||||
if n1.(*BooleanNode).Boolean != n2.(*BooleanNode).Boolean {
|
if n1.(*BooleanNode).value != n2.(*BooleanNode).value {
|
||||||
t.Errorf("Boolean node values don't match (%s and %s)", strconv.FormatBool(n1.(*BooleanNode).Boolean), strconv.FormatBool(n2.(*BooleanNode).Boolean))
|
t.Errorf("Boolean node values don't match (%s and %s)", strconv.FormatBool(n1.(*BooleanNode).value), strconv.FormatBool(n2.(*BooleanNode).value))
|
||||||
} else {
|
} else {
|
||||||
t.Logf("Boolean node values match (%s)", strconv.FormatBool(n1.(*BooleanNode).Boolean))
|
t.Logf("Boolean node values match (%s)", strconv.FormatBool(n1.(*BooleanNode).value))
|
||||||
}
|
}
|
||||||
case BlockNodeType:
|
case BlockNodeType:
|
||||||
if len(n1.(*BlockNode).statements) != len(n2.(*BlockNode).statements) {
|
if len(n1.(*BlockNode).statements) != len(n2.(*BlockNode).statements) {
|
||||||
|
|
@ -854,7 +790,7 @@ func NodeEquality(t *testing.T, n1 Node, n2 Node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, p := range m.parameters {
|
for i, p := range m.parameters {
|
||||||
if !n.parameters[i].Signature.Contains(p.Signature) {
|
if !n.parameters[i].Signature.Matches(p.Signature) {
|
||||||
t.Errorf("Function node parameter signature %d does not match: %s and %s", i, p.Signature, n.parameters[i].Signature)
|
t.Errorf("Function node parameter signature %d does not match: %s and %s", i, p.Signature, n.parameters[i].Signature)
|
||||||
} else if n.parameters[i].Name != p.Name {
|
} else if n.parameters[i].Name != p.Name {
|
||||||
t.Errorf("Function node parameter name %d does not match: %s and %s", i, p.Name, n.parameters[i].Name)
|
t.Errorf("Function node parameter name %d does not match: %s and %s", i, p.Name, n.parameters[i].Name)
|
||||||
|
|
@ -872,11 +808,10 @@ func NodeEquality(t *testing.T, n1 Node, n2 Node) {
|
||||||
a1 := n1.(*AccessNode)
|
a1 := n1.(*AccessNode)
|
||||||
a2 := n2.(*AccessNode)
|
a2 := n2.(*AccessNode)
|
||||||
|
|
||||||
// only care about lexeme; the rest is debug info
|
if a1.property != a2.property {
|
||||||
if a1.property.Lexeme != a2.property.Lexeme {
|
t.Errorf("Access node property does not match: .%s != .%s", a1.property, a2.property)
|
||||||
t.Errorf("Access node property does not match: .%s != .%s", a1.property.Lexeme, a2.property.Lexeme)
|
|
||||||
} else {
|
} else {
|
||||||
t.Logf("Access node property matches: .%s", a1.property.Lexeme)
|
t.Logf("Access node property matches: .%s", a1.property)
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeEquality(t, a1.source, a2.source)
|
NodeEquality(t, a1.source, a2.source)
|
||||||
|
|
@ -890,7 +825,7 @@ func NodeEquality(t *testing.T, n1 Node, n2 Node) {
|
||||||
t.Logf("Both content types are yet to be determined")
|
t.Logf("Both content types are yet to be determined")
|
||||||
} else if l1.content != nil || l2.content != nil {
|
} else if l1.content != nil || l2.content != nil {
|
||||||
t.Errorf("one is nil, one is not")
|
t.Errorf("one is nil, one is not")
|
||||||
} else if !l1.content.Contains(l2.content) {
|
} else if !l1.content.Matches(l2.content) {
|
||||||
t.Errorf("signature doesn't match")
|
t.Errorf("signature doesn't match")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -899,24 +834,110 @@ func NodeEquality(t *testing.T, n1 Node, n2 Node) {
|
||||||
NodeEquality(t, v1, l2.items[i])
|
NodeEquality(t, v1, l2.items[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
case TupleNodeType:
|
|
||||||
t1 := n1.(*TupleNode)
|
|
||||||
t2 := n2.(*TupleNode)
|
|
||||||
|
|
||||||
if len(t1.items) != len(t2.items) {
|
|
||||||
t.Fatalf("tuple item count does not match")
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, v1 := range t1.items {
|
|
||||||
t.Logf("Checking item %d", i)
|
|
||||||
NodeEquality(t, v1, t2.items[i])
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
panic("unimplemented node equality")
|
panic("unimplemented node equality")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SerializeTokens(tokens []Token) string {
|
||||||
|
out := strings.Builder{}
|
||||||
|
level := 0
|
||||||
|
|
||||||
|
for _, token := range tokens {
|
||||||
|
switch token.Type {
|
||||||
|
case TokenPlus:
|
||||||
|
out.WriteString(" + ")
|
||||||
|
case TokenMinus:
|
||||||
|
out.WriteString(" - ")
|
||||||
|
case TokenStar:
|
||||||
|
out.WriteString("*")
|
||||||
|
case TokenSlash:
|
||||||
|
out.WriteString("/")
|
||||||
|
case TokenBang:
|
||||||
|
out.WriteString("!")
|
||||||
|
case TokenSemicolon:
|
||||||
|
out.WriteString(";")
|
||||||
|
case TokenFloat:
|
||||||
|
out.WriteString(token.Lexeme)
|
||||||
|
case TokenString:
|
||||||
|
out.WriteString(fmt.Sprintf("\"%s\"", token.Lexeme))
|
||||||
|
case TokenName:
|
||||||
|
out.WriteString(token.Lexeme)
|
||||||
|
case TokenOpenParenthesis:
|
||||||
|
out.WriteString("(")
|
||||||
|
case TokenCloseParenthesis:
|
||||||
|
out.WriteString(")")
|
||||||
|
case TokenOpenBracket:
|
||||||
|
out.WriteString("[")
|
||||||
|
case TokenCloseBracket:
|
||||||
|
out.WriteString("]")
|
||||||
|
case TokenOpenBrace:
|
||||||
|
out.WriteString("{")
|
||||||
|
level = level + 1
|
||||||
|
case TokenCloseBrace:
|
||||||
|
out.WriteString("}")
|
||||||
|
level = level - 1
|
||||||
|
case TokenTrue:
|
||||||
|
out.WriteString("true")
|
||||||
|
case TokenFalse:
|
||||||
|
out.WriteString("false")
|
||||||
|
case TokenNil:
|
||||||
|
out.WriteString("nil")
|
||||||
|
case TokenFunc:
|
||||||
|
out.WriteString("fn")
|
||||||
|
case TokenReturn:
|
||||||
|
out.WriteString("return ")
|
||||||
|
case TokenWhile:
|
||||||
|
out.WriteString("while ")
|
||||||
|
case TokenVar:
|
||||||
|
out.WriteString("var ")
|
||||||
|
case TokenIf:
|
||||||
|
out.WriteString("if ")
|
||||||
|
case TokenElse:
|
||||||
|
out.WriteString(" else ")
|
||||||
|
case TokenImport:
|
||||||
|
out.WriteString("import ")
|
||||||
|
case TokenComma:
|
||||||
|
out.WriteString(", ")
|
||||||
|
case TokenDot:
|
||||||
|
out.WriteString(".")
|
||||||
|
case TokenColon:
|
||||||
|
out.WriteString(": ")
|
||||||
|
case TokenAssign:
|
||||||
|
out.WriteString(" = ")
|
||||||
|
case TokenDeclare:
|
||||||
|
out.WriteString(" := ")
|
||||||
|
case TokenBangEquals:
|
||||||
|
out.WriteString(" != ")
|
||||||
|
case TokenEquals:
|
||||||
|
out.WriteString(" == ")
|
||||||
|
case TokenGreaterThan:
|
||||||
|
out.WriteString(" > ")
|
||||||
|
case TokenLessThan:
|
||||||
|
out.WriteString(" < ")
|
||||||
|
case TokenGreaterThanOrEqual:
|
||||||
|
out.WriteString(" >= ")
|
||||||
|
case TokenLessThanOrEqual:
|
||||||
|
out.WriteString(" <= ")
|
||||||
|
case TokenDoubleAmpersand:
|
||||||
|
out.WriteString(" && ")
|
||||||
|
case TokenDoublePipe:
|
||||||
|
out.WriteString(" || ")
|
||||||
|
case TokenBreakpoint:
|
||||||
|
out.WriteString("breakpoint")
|
||||||
|
case TokenEOF:
|
||||||
|
out.WriteString(fmt.Sprintf("<error: \"%s\">", token.Lexeme))
|
||||||
|
case TokenHexadecimal:
|
||||||
|
out.WriteString(token.Lexeme)
|
||||||
|
case TokenPipe:
|
||||||
|
out.WriteString(" | ")
|
||||||
|
case TokenError:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out.String()
|
||||||
|
}
|
||||||
|
|
||||||
func TestParser_Parse(t *testing.T) {
|
func TestParser_Parse(t *testing.T) {
|
||||||
t.Logf("Getting test data")
|
t.Logf("Getting test data")
|
||||||
tokenData := GetTokenTestData()
|
tokenData := GetTokenTestData()
|
||||||
|
|
@ -939,31 +960,6 @@ func TestParser_Parse(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, "a"),
|
|
||||||
})
|
|
||||||
|
|
||||||
if !p.acceptAll(TokenName, TokenColon) {
|
|
||||||
t.Fatalf("tokens were not accepted")
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Logf("tokens were accepted")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParser_AcceptAll_TooFew(t *testing.T) {
|
|
||||||
p := NewParser("a", []string{}, []Token{
|
|
||||||
NewToken(TokenName, 0, 1, 0, "a"),
|
|
||||||
})
|
|
||||||
|
|
||||||
if p.acceptAll(TokenName, TokenColon) {
|
|
||||||
t.Fatalf("tokens were incorrectly accepted")
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Logf("tokens were, as expected, not accepted")
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkParser_Parse(b *testing.B) {
|
func BenchmarkParser_Parse(b *testing.B) {
|
||||||
tokenData := GetTokenTestData()
|
tokenData := GetTokenTestData()
|
||||||
|
|
||||||
|
|
|
||||||
271
core/types.go
271
core/types.go
|
|
@ -14,13 +14,11 @@ const (
|
||||||
TypeBoolean
|
TypeBoolean
|
||||||
TypeNil
|
TypeNil
|
||||||
TypeList
|
TypeList
|
||||||
TypeTuple
|
|
||||||
TypeObject
|
TypeObject
|
||||||
TypeFunction
|
TypeFunction
|
||||||
TypeAny
|
TypeAny
|
||||||
TypeComposite
|
TypeComposite
|
||||||
TypeInner
|
TypeInner
|
||||||
TypeNamed
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (t Type) String() string {
|
func (t Type) String() string {
|
||||||
|
|
@ -37,8 +35,6 @@ func (t Type) String() string {
|
||||||
return "nil"
|
return "nil"
|
||||||
case TypeList:
|
case TypeList:
|
||||||
return "list"
|
return "list"
|
||||||
case TypeTuple:
|
|
||||||
return "tuple"
|
|
||||||
case TypeObject:
|
case TypeObject:
|
||||||
return "object"
|
return "object"
|
||||||
case TypeFunction:
|
case TypeFunction:
|
||||||
|
|
@ -72,7 +68,7 @@ func SignatureOf(v Value) TypeSignature {
|
||||||
sig := SignatureOf(p)
|
sig := SignatureOf(p)
|
||||||
if contains == nil {
|
if contains == nil {
|
||||||
contains = sig
|
contains = sig
|
||||||
} else if !contains.Contains(sig) {
|
} else if !contains.Matches(sig) {
|
||||||
contains = &AnySignature{}
|
contains = &AnySignature{}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
@ -96,16 +92,6 @@ func SignatureOf(v Value) TypeSignature {
|
||||||
}
|
}
|
||||||
case *BuiltinFunctionValue:
|
case *BuiltinFunctionValue:
|
||||||
return t.Signature
|
return t.Signature
|
||||||
case *TupleValue:
|
|
||||||
var contains []TypeSignature
|
|
||||||
for _, p := range t.Items {
|
|
||||||
sig := SignatureOf(p)
|
|
||||||
contains = append(contains, sig)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &TupleSignature{
|
|
||||||
contains,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
panic(fmt.Sprintf("unknown value; cannot get signature of %s", v))
|
panic(fmt.Sprintf("unknown value; cannot get signature of %s", v))
|
||||||
|
|
@ -114,12 +100,8 @@ func SignatureOf(v Value) TypeSignature {
|
||||||
type TypeSignature interface {
|
type TypeSignature interface {
|
||||||
Type() Type
|
Type() Type
|
||||||
|
|
||||||
// Contains check if this type signature matches another.
|
// Matches check if this type signature matches another.
|
||||||
// For it to return true, the other type should be a part of this.
|
Matches(TypeSignature) bool
|
||||||
Contains(TypeSignature) bool
|
|
||||||
|
|
||||||
// Equal check if the other signature is the EXACT SAME as this one.
|
|
||||||
Equal(TypeSignature) bool
|
|
||||||
|
|
||||||
// String create a human-readable string version of the value type.
|
// String create a human-readable string version of the value type.
|
||||||
String() string
|
String() string
|
||||||
|
|
@ -131,12 +113,12 @@ func (*NilSignature) Type() Type {
|
||||||
return TypeNil
|
return TypeNil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *NilSignature) Contains(other TypeSignature) bool {
|
func (s *NilSignature) Matches(other TypeSignature) bool {
|
||||||
return other.Type() == TypeNil
|
if other.Type() == TypeComposite {
|
||||||
|
return other.Matches(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *NilSignature) Equal(other TypeSignature) bool {
|
return other.Type() == TypeAny || other.Type() == TypeNil
|
||||||
return other.Type() == TypeNil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*NilSignature) String() string {
|
func (*NilSignature) String() string {
|
||||||
|
|
@ -149,16 +131,16 @@ func (*StringSignature) Type() Type {
|
||||||
return TypeString
|
return TypeString
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *StringSignature) Contains(other TypeSignature) bool {
|
func (s *StringSignature) Matches(other TypeSignature) bool {
|
||||||
return other.Type() == TypeString
|
if other.Type() == TypeComposite {
|
||||||
|
return other.Matches(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *StringSignature) Equal(other TypeSignature) bool {
|
return other.Type() == TypeAny || other.Type() == TypeString
|
||||||
return other.Type() == TypeString
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*StringSignature) String() string {
|
func (*StringSignature) String() string {
|
||||||
return "str"
|
return "string"
|
||||||
}
|
}
|
||||||
|
|
||||||
type FloatSignature struct{}
|
type FloatSignature struct{}
|
||||||
|
|
@ -167,12 +149,12 @@ func (*FloatSignature) Type() Type {
|
||||||
return TypeFloat
|
return TypeFloat
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *FloatSignature) Contains(other TypeSignature) bool {
|
func (s *FloatSignature) Matches(other TypeSignature) bool {
|
||||||
return other.Type() == TypeFloat
|
if other.Type() == TypeComposite {
|
||||||
|
return other.Matches(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *FloatSignature) Equal(other TypeSignature) bool {
|
return other.Type() == TypeAny || other.Type() == TypeFloat
|
||||||
return other.Type() == TypeFloat
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*FloatSignature) String() string {
|
func (*FloatSignature) String() string {
|
||||||
|
|
@ -185,12 +167,12 @@ func (*IntegerSignature) Type() Type {
|
||||||
return TypeInteger
|
return TypeInteger
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *IntegerSignature) Contains(other TypeSignature) bool {
|
func (s *IntegerSignature) Matches(other TypeSignature) bool {
|
||||||
return other.Type() == TypeInteger
|
if other.Type() == TypeComposite {
|
||||||
|
return other.Matches(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *IntegerSignature) Equal(other TypeSignature) bool {
|
return other.Type() == TypeAny || other.Type() == TypeInteger
|
||||||
return other.Type() == TypeInteger
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*IntegerSignature) String() string {
|
func (*IntegerSignature) String() string {
|
||||||
|
|
@ -203,12 +185,12 @@ func (*BooleanSignature) Type() Type {
|
||||||
return TypeBoolean
|
return TypeBoolean
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *BooleanSignature) Contains(other TypeSignature) bool {
|
func (s *BooleanSignature) Matches(other TypeSignature) bool {
|
||||||
return other.Type() == TypeBoolean
|
if other.Type() == TypeComposite {
|
||||||
|
return other.Matches(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *BooleanSignature) Equal(other TypeSignature) bool {
|
return other.Type() == TypeAny || other.Type() == TypeBoolean
|
||||||
return other.Type() == TypeBoolean
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*BooleanSignature) String() string {
|
func (*BooleanSignature) String() string {
|
||||||
|
|
@ -223,75 +205,16 @@ func (*ListSignature) Type() Type {
|
||||||
return TypeList
|
return TypeList
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ListSignature) Contains(other TypeSignature) bool {
|
func (s *ListSignature) Matches(other TypeSignature) bool {
|
||||||
return other.Type() == TypeList && other.(*ListSignature).Contents.Contains(s.Contents)
|
if other.Type() == TypeComposite {
|
||||||
|
return other.Matches(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ListSignature) Equal(other TypeSignature) bool {
|
return other.Type() == TypeAny || (other.Type() == TypeList && other.(*ListSignature).Contents.Matches(s.Contents))
|
||||||
return other.Type() == TypeList && other.(*ListSignature).Contents.Equal(s.Contents)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ListSignature) String() string {
|
func (s *ListSignature) String() string {
|
||||||
return fmt.Sprintf("[%s]", s.Contents)
|
return fmt.Sprintf("list[%s]", s.Contents)
|
||||||
}
|
|
||||||
|
|
||||||
type TupleSignature struct {
|
|
||||||
Contents []TypeSignature
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*TupleSignature) Type() Type {
|
|
||||||
return TypeTuple
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *TupleSignature) Contains(other TypeSignature) bool {
|
|
||||||
if other.Type() != TypeTuple || len(other.(*TupleSignature).Contents) != len(s.Contents) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
n := other.(*TupleSignature).Contents
|
|
||||||
for i, c := range s.Contents {
|
|
||||||
if !c.Contains(n[i]) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *TupleSignature) Equal(other TypeSignature) bool {
|
|
||||||
if other.Type() != TypeTuple {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
n := other.(*TupleSignature).Contents
|
|
||||||
for i, c := range s.Contents {
|
|
||||||
if !c.Equal(n[i]) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *TupleSignature) String() string {
|
|
||||||
|
|
||||||
sb := strings.Builder{}
|
|
||||||
|
|
||||||
sb.WriteString("(")
|
|
||||||
for i, t := range s.Contents {
|
|
||||||
if i > 0 {
|
|
||||||
sb.WriteString(",")
|
|
||||||
sb.WriteString(" ")
|
|
||||||
}
|
|
||||||
sb.WriteString(t.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(s.Contents) <= 1 {
|
|
||||||
sb.WriteString(",")
|
|
||||||
}
|
|
||||||
sb.WriteString(")")
|
|
||||||
|
|
||||||
return sb.String()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type ObjectSignature struct {
|
type ObjectSignature struct {
|
||||||
|
|
@ -302,13 +225,25 @@ func (*ObjectSignature) Type() Type {
|
||||||
return TypeObject
|
return TypeObject
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ObjectSignature) Contains(other TypeSignature) bool {
|
func (s *ObjectSignature) Matches(other TypeSignature) bool {
|
||||||
|
if other.Type() == TypeComposite {
|
||||||
|
return other.Matches(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
if other.Type() == TypeAny {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
if other.Type() != TypeObject {
|
if other.Type() != TypeObject {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
o := other.(*ObjectSignature)
|
o := other.(*ObjectSignature)
|
||||||
|
|
||||||
|
if len(o.Members) != len(s.Members) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
for name, member := range s.Members {
|
for name, member := range s.Members {
|
||||||
v, ok := o.Members[name]
|
v, ok := o.Members[name]
|
||||||
|
|
||||||
|
|
@ -316,29 +251,7 @@ func (s *ObjectSignature) Contains(other TypeSignature) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if !v.Contains(member) {
|
if !v.Matches(member) {
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ObjectSignature) Equal(other TypeSignature) bool {
|
|
||||||
if other.Type() != TypeObject {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(s.Members) != len(other.(*ObjectSignature).Members) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
for name, member := range s.Members {
|
|
||||||
v, ok := other.(*ObjectSignature).Members[name]
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if !v.Equal(member) {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -359,14 +272,22 @@ func (*FunctionSignature) Type() Type {
|
||||||
return TypeFunction
|
return TypeFunction
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *FunctionSignature) Contains(other TypeSignature) bool {
|
func (s *FunctionSignature) Matches(other TypeSignature) bool {
|
||||||
|
if other.Type() == TypeComposite {
|
||||||
|
return other.Matches(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
if other.Type() == TypeAny {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
if other.Type() != TypeFunction {
|
if other.Type() != TypeFunction {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
f := other.(*FunctionSignature)
|
f := other.(*FunctionSignature)
|
||||||
|
|
||||||
if !s.Out.Contains(f.Out) {
|
if !s.Out.Matches(f.Out) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -376,7 +297,7 @@ func (s *FunctionSignature) Contains(other TypeSignature) bool {
|
||||||
|
|
||||||
for i, p := range s.In {
|
for i, p := range s.In {
|
||||||
v := f.In[i]
|
v := f.In[i]
|
||||||
if !p.Contains(v) {
|
if !p.Matches(v) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -384,30 +305,10 @@ func (s *FunctionSignature) Contains(other TypeSignature) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *FunctionSignature) Equal(other TypeSignature) bool {
|
|
||||||
if other.Type() != TypeFunction {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
f := other.(*FunctionSignature)
|
|
||||||
if len(f.In) != len(s.In) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, p := range s.In {
|
|
||||||
v := f.In[i]
|
|
||||||
if !p.Equal(v) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return f.Out.Equal(s.Out)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *FunctionSignature) String() string {
|
func (s *FunctionSignature) String() string {
|
||||||
b := strings.Builder{}
|
b := strings.Builder{}
|
||||||
|
|
||||||
b.WriteString("fn(")
|
b.WriteString("func(")
|
||||||
|
|
||||||
for i, t := range s.In {
|
for i, t := range s.In {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
|
|
@ -418,7 +319,7 @@ func (s *FunctionSignature) String() string {
|
||||||
|
|
||||||
b.WriteString(")")
|
b.WriteString(")")
|
||||||
if s.Out.Type() != TypeNil {
|
if s.Out.Type() != TypeNil {
|
||||||
b.WriteString(" -> ")
|
b.WriteString(" ")
|
||||||
b.WriteString(s.Out.String())
|
b.WriteString(s.Out.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -431,14 +332,10 @@ func (*AnySignature) Type() Type {
|
||||||
return TypeAny
|
return TypeAny
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*AnySignature) Contains(_ TypeSignature) bool {
|
func (*AnySignature) Matches(_ TypeSignature) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *AnySignature) Equal(t TypeSignature) bool {
|
|
||||||
return t.Type() == TypeAny
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*AnySignature) String() string {
|
func (*AnySignature) String() string {
|
||||||
return "any"
|
return "any"
|
||||||
}
|
}
|
||||||
|
|
@ -452,72 +349,24 @@ func (*CompositeSignature) Type() Type {
|
||||||
return TypeComposite
|
return TypeComposite
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *CompositeSignature) Contains(other TypeSignature) bool {
|
func (s *CompositeSignature) Matches(other TypeSignature) bool {
|
||||||
return s.A.Contains(other) || s.B.Contains(other)
|
return s.A.Matches(other) || s.B.Matches(other)
|
||||||
}
|
|
||||||
|
|
||||||
func (s *CompositeSignature) Equal(t TypeSignature) bool {
|
|
||||||
return t.Type() == TypeComposite && s.A.Equal(t.(*CompositeSignature).A) && s.B.Equal(t.(*CompositeSignature).B)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *CompositeSignature) String() string {
|
func (s *CompositeSignature) String() string {
|
||||||
return fmt.Sprintf("%s|%s", s.A, s.B)
|
return fmt.Sprintf("%s|%s", s.A, s.B)
|
||||||
}
|
}
|
||||||
|
|
||||||
func quickComposite(a ...TypeSignature) TypeSignature {
|
|
||||||
switch len(a) {
|
|
||||||
case 0:
|
|
||||||
panic("quick composite: empty array")
|
|
||||||
case 1:
|
|
||||||
return a[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
s := a[0]
|
|
||||||
for i := 1; i < len(a); i++ {
|
|
||||||
v := a[i]
|
|
||||||
s = &CompositeSignature{
|
|
||||||
A: s,
|
|
||||||
B: v,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
type InnerSignature struct{}
|
type InnerSignature struct{}
|
||||||
|
|
||||||
func (*InnerSignature) Type() Type {
|
func (*InnerSignature) Type() Type {
|
||||||
return TypeInner
|
return TypeInner
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*InnerSignature) Contains(_ TypeSignature) bool {
|
func (*InnerSignature) Matches(_ TypeSignature) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *InnerSignature) Equal(t TypeSignature) bool {
|
|
||||||
return t.Type() == TypeInner
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*InnerSignature) String() string {
|
func (*InnerSignature) String() string {
|
||||||
return "inner"
|
return "inner"
|
||||||
}
|
}
|
||||||
|
|
||||||
type NamedSignature struct {
|
|
||||||
Name string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*NamedSignature) Type() Type {
|
|
||||||
return TypeNamed
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *NamedSignature) Contains(t TypeSignature) bool {
|
|
||||||
return t.Type() == TypeNamed && s.Name == t.(*NamedSignature).Name
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *NamedSignature) Equal(t TypeSignature) bool {
|
|
||||||
return t.Type() == TypeNamed && s.Name == t.(*NamedSignature).Name
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *NamedSignature) String() string {
|
|
||||||
return s.Name
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"math/big"
|
"math/big"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ValueType int
|
type ValueType int
|
||||||
|
|
@ -18,7 +17,6 @@ const (
|
||||||
IntegerValueType
|
IntegerValueType
|
||||||
StringValueType
|
StringValueType
|
||||||
ListValueType
|
ListValueType
|
||||||
TupleValueType
|
|
||||||
ObjectValueType
|
ObjectValueType
|
||||||
FunctionValueType
|
FunctionValueType
|
||||||
BuiltinFunctionValueType
|
BuiltinFunctionValueType
|
||||||
|
|
@ -41,8 +39,6 @@ func (v ValueType) String() string {
|
||||||
return "string"
|
return "string"
|
||||||
case ListValueType:
|
case ListValueType:
|
||||||
return "list"
|
return "list"
|
||||||
case TupleValueType:
|
|
||||||
return "tuple"
|
|
||||||
case FunctionValueType:
|
case FunctionValueType:
|
||||||
return "function"
|
return "function"
|
||||||
case BuiltinFunctionValueType:
|
case BuiltinFunctionValueType:
|
||||||
|
|
@ -223,8 +219,8 @@ func (v *ObjectValue) Equals(other Value) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
var ObjectPrototype = map[string]*BuiltinFunctionValue{
|
var ObjectPrototype = map[string]Value{
|
||||||
"set": {
|
"set": &BuiltinFunctionValue{
|
||||||
"set",
|
"set",
|
||||||
&FunctionSignature{
|
&FunctionSignature{
|
||||||
[]TypeSignature{&StringSignature{}, &ListSignature{}},
|
[]TypeSignature{&StringSignature{}, &ListSignature{}},
|
||||||
|
|
@ -282,12 +278,7 @@ func (v *FloatValue) Type() ValueType {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *FloatValue) String() string {
|
func (v *FloatValue) String() string {
|
||||||
s := strconv.FormatFloat(v.Number, 'g', -1, FloatSize)
|
return strconv.FormatFloat(v.Number, 'g', -1, FloatSize)
|
||||||
if strings.Index(s, ".") == -1 {
|
|
||||||
s += ".0"
|
|
||||||
}
|
|
||||||
|
|
||||||
return s
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *FloatValue) DebugString() string {
|
func (v *FloatValue) DebugString() string {
|
||||||
|
|
@ -606,88 +597,6 @@ func (v *ListValue) Clone() Value {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type TupleValue struct {
|
|
||||||
Items []Value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *TupleValue) Type() ValueType {
|
|
||||||
return TupleValueType
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *TupleValue) String() string {
|
|
||||||
out := "("
|
|
||||||
for i, item := range v.Items {
|
|
||||||
if i != 0 {
|
|
||||||
out += ", "
|
|
||||||
}
|
|
||||||
out += item.DebugString()
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(v.Items) <= 1 {
|
|
||||||
out += ","
|
|
||||||
}
|
|
||||||
out += ")"
|
|
||||||
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *TupleValue) DebugString() string {
|
|
||||||
return v.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *TupleValue) Clone() Value {
|
|
||||||
n := make([]Value, len(v.Items))
|
|
||||||
for i, item := range v.Items {
|
|
||||||
n[i] = item.Clone()
|
|
||||||
}
|
|
||||||
return &TupleValue{
|
|
||||||
n,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *TupleValue) Equals(other Value) bool {
|
|
||||||
if other.Type() != TupleValueType {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
t := other.(*TupleValue).Items
|
|
||||||
for i, item := range v.Items {
|
|
||||||
if !item.Equals(t[i]) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
var TuplePrototype = map[string]*BuiltinFunctionValue{
|
|
||||||
"at": &BuiltinFunctionValue{
|
|
||||||
"at",
|
|
||||||
&FunctionSignature{
|
|
||||||
[]TypeSignature{&IntegerSignature{}},
|
|
||||||
&InnerSignature{},
|
|
||||||
},
|
|
||||||
func(vm *VM, this Value, args []Value) (Value, error) {
|
|
||||||
i := args[0].(*IntegerValue).Number.Int64()
|
|
||||||
|
|
||||||
if i < 0 || i >= int64(len(this.(*TupleValue).Items)) {
|
|
||||||
return nil, errors.New(fmt.Sprintf("index %x out of range", i))
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.(*TupleValue).Items[i], nil
|
|
||||||
},
|
|
||||||
nil,
|
|
||||||
true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *TupleValue) Get(key string) (Value, error) {
|
|
||||||
if prop, ok := TuplePrototype[key]; ok {
|
|
||||||
return prop, nil
|
|
||||||
}
|
|
||||||
return nil, errors.New(fmt.Sprintf("tuple has no property \"%s\"", key))
|
|
||||||
}
|
|
||||||
|
|
||||||
type FunctionValue struct {
|
type FunctionValue struct {
|
||||||
Name string
|
Name string
|
||||||
Params []FunctionParameter
|
Params []FunctionParameter
|
||||||
|
|
@ -742,7 +651,7 @@ func (v *BuiltinFunctionValue) Type() ValueType {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *BuiltinFunctionValue) String() string {
|
func (v *BuiltinFunctionValue) String() string {
|
||||||
return fmt.Sprintf("<function builtin name=%s>", v.Name)
|
return fmt.Sprintf("<function name=%s builtin>", v.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *BuiltinFunctionValue) DebugString() string {
|
func (v *BuiltinFunctionValue) DebugString() string {
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ func CompareValues(t *testing.T, got Value, want Value) {
|
||||||
t.Errorf("builtin function name mismatch: got %v, want %v", n.Name, m.Name)
|
t.Errorf("builtin function name mismatch: got %v, want %v", n.Name, m.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !n.Signature.Contains(m.Signature) {
|
if !n.Signature.Matches(m.Signature) {
|
||||||
t.Errorf("builtin function parameter count mismatch: got %v, want %v", n, m)
|
t.Errorf("builtin function parameter count mismatch: got %v, want %v", n, m)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -96,19 +96,6 @@ func CompareValues(t *testing.T, got Value, want Value) {
|
||||||
CompareValues(t, v, m.Members[k])
|
CompareValues(t, v, m.Members[k])
|
||||||
}
|
}
|
||||||
|
|
||||||
case TupleValueType:
|
|
||||||
n := got.(*TupleValue)
|
|
||||||
m := want.(*TupleValue)
|
|
||||||
|
|
||||||
if len(n.Items) != len(m.Items) {
|
|
||||||
t.Fatalf("tuple item count mismatch: got %d items, want %d items", len(n.Items), len(m.Items))
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, v := range n.Items {
|
|
||||||
t.Logf("comparing tuple item #%d", i)
|
|
||||||
CompareValues(t, v, m.Items[i])
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
panic("unimplemented comparison")
|
panic("unimplemented comparison")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
145
core/vm.go
145
core/vm.go
|
|
@ -41,8 +41,6 @@ const (
|
||||||
InstructionMulInt
|
InstructionMulInt
|
||||||
// InstructionDivInt pop two ints and divide the second by the first
|
// InstructionDivInt pop two ints and divide the second by the first
|
||||||
InstructionDivInt
|
InstructionDivInt
|
||||||
// InstructionModInt pop two ints and compute the modulo of the first by the second
|
|
||||||
InstructionModInt
|
|
||||||
// InstructionNegateInt negate the int; if it was positive, make it negative, and vice versa.
|
// InstructionNegateInt negate the int; if it was positive, make it negative, and vice versa.
|
||||||
InstructionNegateInt
|
InstructionNegateInt
|
||||||
|
|
||||||
|
|
@ -101,8 +99,8 @@ const (
|
||||||
|
|
||||||
// InstructionStringConversion Take the top value on the stack and convert it to a string
|
// InstructionStringConversion Take the top value on the stack and convert it to a string
|
||||||
InstructionStringConversion
|
InstructionStringConversion
|
||||||
// InstructionConcatStrings Add two strings together, with the second value on the stack as left and the top as right
|
// InstructionStringConcatenation Add two strings together, with the second value on the stack as left and the top as right
|
||||||
InstructionConcatStrings
|
InstructionStringConcatenation
|
||||||
|
|
||||||
// InstructionSwap swap the two top items on the stack (1, 2 -> 2, 1)
|
// InstructionSwap swap the two top items on the stack (1, 2 -> 2, 1)
|
||||||
InstructionSwap
|
InstructionSwap
|
||||||
|
|
@ -123,33 +121,17 @@ const (
|
||||||
// InstructionNil Push a nil literal to the stack
|
// InstructionNil Push a nil literal to the stack
|
||||||
InstructionNil
|
InstructionNil
|
||||||
|
|
||||||
|
// InstructionNewList Push a new (empty) list to the stack
|
||||||
|
InstructionNewList
|
||||||
// InstructionAppend Append to a list. stack: (... > list > item) => (... > list)
|
// InstructionAppend Append to a list. stack: (... > list > item) => (... > list)
|
||||||
InstructionAppend
|
InstructionAppend
|
||||||
// InstructionFormList Form items on the stack into a list. The 2 bytes after the instructions are the amount of
|
// 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 minus one. (value of 0 => 1 item, value of 1 => 2 items, etc.) The order is reversed compared
|
||||||
// list.
|
// to on the stack; the top value on the stack is the last in the list.
|
||||||
InstructionFormList
|
InstructionFormList
|
||||||
// InstructionConcatLists concatenate lists, producing a new list with the values of both lists. Pops two lists.
|
// InstructionConcatLists concatenate lists, producing a new list with the values of both lists. Pops two lists.
|
||||||
InstructionConcatLists
|
InstructionConcatLists
|
||||||
|
|
||||||
// InstructionFormTuple pop n+1 (u16) items from the stack, and create a new tuple with the items. The top value
|
|
||||||
// on the stack is the last value in the tuple.
|
|
||||||
InstructionFormTuple
|
|
||||||
// InstructionDestructureTuple pop a tuple, and push all its items to the stack, with the top item on the stack
|
|
||||||
// being the last item in the tuple.
|
|
||||||
InstructionDestructureTuple
|
|
||||||
|
|
||||||
// InstructionIndexList index into a list. The lower item is the container, and the top item
|
|
||||||
// is the index. [..., container, index] -> [..., item]
|
|
||||||
InstructionIndexList
|
|
||||||
// InstructionIndexTuple index into a tuple. The lower item is the container, and the top item
|
|
||||||
// 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 the character
|
|
||||||
// at the position
|
|
||||||
InstructionIndexString
|
|
||||||
|
|
||||||
// InstructionBreakpoint for debugging purposes
|
// InstructionBreakpoint for debugging purposes
|
||||||
InstructionBreakpoint
|
InstructionBreakpoint
|
||||||
)
|
)
|
||||||
|
|
@ -234,7 +216,7 @@ func (b Bytecode) String() string {
|
||||||
return "ASCEND"
|
return "ASCEND"
|
||||||
case InstructionStringConversion:
|
case InstructionStringConversion:
|
||||||
return "STRING_CONVERSION"
|
return "STRING_CONVERSION"
|
||||||
case InstructionConcatStrings:
|
case InstructionStringConcatenation:
|
||||||
return "STRING_CONCATENATION"
|
return "STRING_CONCATENATION"
|
||||||
case InstructionSwap:
|
case InstructionSwap:
|
||||||
return "SWAP"
|
return "SWAP"
|
||||||
|
|
@ -246,6 +228,8 @@ func (b Bytecode) String() string {
|
||||||
return "FORM_LIST"
|
return "FORM_LIST"
|
||||||
case InstructionBreakpoint:
|
case InstructionBreakpoint:
|
||||||
return "BREAKPOINT"
|
return "BREAKPOINT"
|
||||||
|
case InstructionNewList:
|
||||||
|
return "NEW_LIST"
|
||||||
case InstructionAppend:
|
case InstructionAppend:
|
||||||
return "APPEND"
|
return "APPEND"
|
||||||
case InstructionAccessProperty:
|
case InstructionAccessProperty:
|
||||||
|
|
@ -254,14 +238,6 @@ func (b Bytecode) String() string {
|
||||||
return "CONCAT_LISTS"
|
return "CONCAT_LISTS"
|
||||||
case InstructionDuplicate:
|
case InstructionDuplicate:
|
||||||
return "DUPLICATE"
|
return "DUPLICATE"
|
||||||
case InstructionFormTuple:
|
|
||||||
return "FORM_TUPLE"
|
|
||||||
case InstructionIndexList:
|
|
||||||
return "INDEX_LIST"
|
|
||||||
case InstructionIndexTuple:
|
|
||||||
return "INDEX_TUPLE"
|
|
||||||
case InstructionDestructureTuple:
|
|
||||||
return "DESTRUCTURE_TUPLE"
|
|
||||||
}
|
}
|
||||||
return "UNDEFINED"
|
return "UNDEFINED"
|
||||||
}
|
}
|
||||||
|
|
@ -271,7 +247,7 @@ type Chunk struct {
|
||||||
Constants []Value
|
Constants []Value
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Chunk) String() string {
|
func (c Chunk) String() string {
|
||||||
b := strings.Builder{}
|
b := strings.Builder{}
|
||||||
|
|
||||||
b.WriteString("=v= chunk =v=\n")
|
b.WriteString("=v= chunk =v=\n")
|
||||||
|
|
@ -344,7 +320,7 @@ func RegisterGOBTypes() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Chunk) Serialize() []byte {
|
func (c Chunk) Serialize() []byte {
|
||||||
b := bytes.Buffer{}
|
b := bytes.Buffer{}
|
||||||
|
|
||||||
e := gob.NewEncoder(&b)
|
e := gob.NewEncoder(&b)
|
||||||
|
|
@ -573,13 +549,7 @@ var DefaultGlobals = map[string]Value{
|
||||||
"int": &BuiltinFunctionValue{
|
"int": &BuiltinFunctionValue{
|
||||||
"int",
|
"int",
|
||||||
&FunctionSignature{
|
&FunctionSignature{
|
||||||
[]TypeSignature{
|
[]TypeSignature{&AnySignature{}},
|
||||||
quickComposite(
|
|
||||||
&IntegerSignature{},
|
|
||||||
&FloatSignature{},
|
|
||||||
&StringSignature{},
|
|
||||||
),
|
|
||||||
},
|
|
||||||
&CompositeSignature{
|
&CompositeSignature{
|
||||||
&IntegerSignature{},
|
&IntegerSignature{},
|
||||||
&NilSignature{},
|
&NilSignature{},
|
||||||
|
|
@ -600,7 +570,7 @@ var DefaultGlobals = map[string]Value{
|
||||||
|
|
||||||
return &IntegerValue{n}, nil
|
return &IntegerValue{n}, nil
|
||||||
default:
|
default:
|
||||||
return nil, errors.New(fmt.Sprintf("%s cannot become an integer (undefined)", v))
|
return nil, errors.New(fmt.Sprintf("%s cannot become an integer", v))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
nil,
|
nil,
|
||||||
|
|
@ -609,38 +579,35 @@ var DefaultGlobals = map[string]Value{
|
||||||
"float": &BuiltinFunctionValue{
|
"float": &BuiltinFunctionValue{
|
||||||
"float",
|
"float",
|
||||||
&FunctionSignature{
|
&FunctionSignature{
|
||||||
[]TypeSignature{
|
[]TypeSignature{&AnySignature{}},
|
||||||
quickComposite(
|
&CompositeSignature{
|
||||||
&FloatSignature{},
|
&FloatSignature{},
|
||||||
&IntegerSignature{},
|
&NilSignature{},
|
||||||
&StringSignature{},
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
&FloatSignature{},
|
|
||||||
},
|
},
|
||||||
func(vm *VM, _ Value, args []Value) (Value, error) {
|
func(vm *VM, _ Value, args []Value) (Value, error) {
|
||||||
switch v := args[0].(type) {
|
switch v := args[0].(type) {
|
||||||
case *IntegerValue:
|
case *IntegerValue:
|
||||||
n, _ := v.Number.Float64()
|
n, _ := v.Number.Float64()
|
||||||
return &FloatValue{n}, nil
|
return &FloatValue{n}, nil // this might need to clone the value instead
|
||||||
case *FloatValue:
|
case *FloatValue:
|
||||||
return v.Clone(), nil
|
return &FloatValue{v.Number}, nil
|
||||||
case *StringValue:
|
case *StringValue:
|
||||||
num, err := strconv.ParseFloat(v.Text, FloatSize)
|
num, err := strconv.ParseFloat(v.Text, FloatSize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &FloatValue{}, nil
|
return &NilValue{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return &FloatValue{num}, nil
|
return &FloatValue{num}, nil
|
||||||
default:
|
default:
|
||||||
return nil, errors.New(fmt.Sprintf("%s cannot become an integer (undefined)", v))
|
return nil, errors.New(fmt.Sprintf("%s cannot become an integer", v))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
nil,
|
nil,
|
||||||
true,
|
true,
|
||||||
},
|
},
|
||||||
"typeof": &BuiltinFunctionValue{
|
"type": &BuiltinFunctionValue{
|
||||||
Name: "typeof",
|
Name: "type",
|
||||||
Signature: &FunctionSignature{
|
Signature: &FunctionSignature{
|
||||||
In: []TypeSignature{&AnySignature{}},
|
In: []TypeSignature{&AnySignature{}},
|
||||||
Out: &StringSignature{},
|
Out: &StringSignature{},
|
||||||
|
|
@ -693,12 +660,12 @@ var DefaultGlobals = map[string]Value{
|
||||||
"roundd": &BuiltinFunctionValue{
|
"roundd": &BuiltinFunctionValue{
|
||||||
"roundd",
|
"roundd",
|
||||||
&FunctionSignature{
|
&FunctionSignature{
|
||||||
[]TypeSignature{&FloatSignature{}, &IntegerSignature{}},
|
[]TypeSignature{&FloatSignature{}, &FloatSignature{}},
|
||||||
&FloatSignature{},
|
&FloatSignature{},
|
||||||
},
|
},
|
||||||
func(vm *VM, this Value, args []Value) (Value, error) {
|
func(vm *VM, this Value, args []Value) (Value, error) {
|
||||||
x := args[0].(*FloatValue).Number
|
x := args[0].(*FloatValue).Number
|
||||||
decimals, _ := args[1].(*IntegerValue).Number.Float64()
|
decimals := args[1].(*FloatValue).Number
|
||||||
multiplier := math.Pow(10, decimals)
|
multiplier := math.Pow(10, decimals)
|
||||||
return &FloatValue{math.Round(x*multiplier) / multiplier}, nil
|
return &FloatValue{math.Round(x*multiplier) / multiplier}, nil
|
||||||
},
|
},
|
||||||
|
|
@ -812,12 +779,6 @@ func (vm *VM) Next() bool {
|
||||||
|
|
||||||
vm.Stack.Push(&IntegerValue{new(big.Int).Div(l, r)})
|
vm.Stack.Push(&IntegerValue{new(big.Int).Div(l, r)})
|
||||||
|
|
||||||
case InstructionModInt:
|
|
||||||
r := vm.Stack.Pop().(*IntegerValue).Number
|
|
||||||
l := vm.Stack.Pop().(*IntegerValue).Number
|
|
||||||
|
|
||||||
vm.Stack.Push(&IntegerValue{new(big.Int).Mod(l, r)})
|
|
||||||
|
|
||||||
case InstructionNegateInt:
|
case InstructionNegateInt:
|
||||||
v := vm.Stack.Pop().(*IntegerValue).Number
|
v := vm.Stack.Pop().(*IntegerValue).Number
|
||||||
|
|
||||||
|
|
@ -1002,6 +963,9 @@ func (vm *VM) Next() bool {
|
||||||
items,
|
items,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
case InstructionNewList:
|
||||||
|
vm.Stack.Push(&ListValue{[]Value{}})
|
||||||
|
|
||||||
case InstructionAppend:
|
case InstructionAppend:
|
||||||
value := vm.Stack.Pop()
|
value := vm.Stack.Pop()
|
||||||
list := vm.Stack.Pop().(*ListValue)
|
list := vm.Stack.Pop().(*ListValue)
|
||||||
|
|
@ -1016,23 +980,6 @@ func (vm *VM) Next() bool {
|
||||||
append(l.Items, r.Items...),
|
append(l.Items, r.Items...),
|
||||||
})
|
})
|
||||||
|
|
||||||
case InstructionFormTuple:
|
|
||||||
n := int(vm.NextU16())
|
|
||||||
|
|
||||||
items := make([]Value, n)
|
|
||||||
for i := n - 1; i >= 0; i-- {
|
|
||||||
items[i] = vm.Stack.Pop()
|
|
||||||
}
|
|
||||||
|
|
||||||
vm.Stack.Push(&TupleValue{
|
|
||||||
items,
|
|
||||||
})
|
|
||||||
|
|
||||||
case InstructionDestructureTuple:
|
|
||||||
t := vm.Stack.Pop().(*TupleValue)
|
|
||||||
|
|
||||||
vm.Stack.Push(t.Items...)
|
|
||||||
|
|
||||||
case InstructionDescend:
|
case InstructionDescend:
|
||||||
vm.descend()
|
vm.descend()
|
||||||
|
|
||||||
|
|
@ -1043,7 +990,7 @@ func (vm *VM) Next() bool {
|
||||||
v := vm.Stack.Pop()
|
v := vm.Stack.Pop()
|
||||||
vm.Stack.Push(&StringValue{v.String()})
|
vm.Stack.Push(&StringValue{v.String()})
|
||||||
|
|
||||||
case InstructionConcatStrings:
|
case InstructionStringConcatenation:
|
||||||
r := vm.Stack.Pop().(*StringValue).Text
|
r := vm.Stack.Pop().(*StringValue).Text
|
||||||
l := vm.Stack.Pop().(*StringValue).Text
|
l := vm.Stack.Pop().(*StringValue).Text
|
||||||
|
|
||||||
|
|
@ -1076,42 +1023,6 @@ func (vm *VM) Next() bool {
|
||||||
|
|
||||||
vm.Stack.Push(member)
|
vm.Stack.Push(member)
|
||||||
|
|
||||||
case InstructionIndexList:
|
|
||||||
i := vm.Stack.Pop().(*IntegerValue)
|
|
||||||
l := vm.Stack.Pop().(*ListValue)
|
|
||||||
|
|
||||||
n := int(i.Number.Int64())
|
|
||||||
|
|
||||||
if n < 0 || len(l.Items) <= n {
|
|
||||||
vm.error(fmt.Sprintf("index %d out of bounds", n))
|
|
||||||
}
|
|
||||||
|
|
||||||
vm.Stack.Push(l.Items[n].Clone())
|
|
||||||
|
|
||||||
case InstructionIndexTuple:
|
|
||||||
i := vm.Stack.Pop().(*IntegerValue)
|
|
||||||
t := vm.Stack.Pop().(*TupleValue)
|
|
||||||
|
|
||||||
n := int(i.Number.Int64())
|
|
||||||
|
|
||||||
if n < 0 || len(t.Items) <= n {
|
|
||||||
vm.error(fmt.Sprintf("index %d out of bounds", n))
|
|
||||||
}
|
|
||||||
|
|
||||||
vm.Stack.Push(t.Items[n].Clone())
|
|
||||||
|
|
||||||
case InstructionIndexString:
|
|
||||||
i := vm.Stack.Pop().(*IntegerValue)
|
|
||||||
s := vm.Stack.Pop().(*StringValue)
|
|
||||||
|
|
||||||
n := int(i.Number.Int64())
|
|
||||||
|
|
||||||
if n < 0 || len(s.Text) <= n {
|
|
||||||
vm.error(fmt.Sprintf("index %d out of bounds", n))
|
|
||||||
}
|
|
||||||
|
|
||||||
vm.Stack.Push(&StringValue{string(s.Text[n])})
|
|
||||||
|
|
||||||
case InstructionBreakpoint:
|
case InstructionBreakpoint:
|
||||||
/*
|
/*
|
||||||
// I'm keeping this
|
// I'm keeping this
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -616,28 +615,6 @@ func GetExecutionTestData() map[string]struct {
|
||||||
},
|
},
|
||||||
[]map[string]Value{},
|
[]map[string]Value{},
|
||||||
},
|
},
|
||||||
"form_tuple": {
|
|
||||||
&Chunk{
|
|
||||||
Bytecode: []Bytecode{
|
|
||||||
InstructionConstant, 0,
|
|
||||||
InstructionConstant, 1,
|
|
||||||
InstructionFormTuple, 0, 2,
|
|
||||||
},
|
|
||||||
Constants: []Value{
|
|
||||||
&IntegerValue{big.NewInt(1)},
|
|
||||||
&IntegerValue{big.NewInt(2)},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
[]Value{
|
|
||||||
&TupleValue{
|
|
||||||
Items: []Value{
|
|
||||||
&IntegerValue{big.NewInt(1)},
|
|
||||||
&IntegerValue{big.NewInt(2)},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
[]map[string]Value{},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
2
emoji.ang
Normal file
2
emoji.ang
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
|
||||||
|
write(char(0x12) + char(0x85) + char(0x07))
|
||||||
11
era3.ang
Normal file
11
era3.ang
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
fn counter() -> (fn() -> int) {
|
||||||
|
i := 0
|
||||||
|
|
||||||
|
fn() -> int { i = i + 1 }
|
||||||
|
}
|
||||||
|
|
||||||
|
next := counter()
|
||||||
|
|
||||||
|
println(next())
|
||||||
|
println(next())
|
||||||
|
println(next())
|
||||||
|
|
@ -1,20 +1,19 @@
|
||||||
|
|
||||||
println("Bonjour à tout!")
|
write("Bonjour à tout!");
|
||||||
|
|
||||||
if 1 == 2 {
|
if 1 == 2 {
|
||||||
# unreachable
|
# unreachable
|
||||||
println("Wooot?? One does equal 2????")
|
|
||||||
} else {
|
} else {
|
||||||
println("Hooray! One does not equal 2!")
|
write("Hooray! One does not equal 2!");
|
||||||
}
|
}
|
||||||
|
|
||||||
for n in 0..10 {
|
for (var n = 1; n < 10; n = n + 1) {
|
||||||
println("Run number " + str(n))
|
write("Run number " + str(n));
|
||||||
}
|
}
|
||||||
|
|
||||||
a := 2
|
var a = 2;
|
||||||
|
|
||||||
println(3 * a*a + 10 / 3)
|
write(3 * a*a + 10 / 3);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,17 @@
|
||||||
|
|
||||||
# calculate fibonacci numbers with a loop
|
# calculate fibonacci numbers with a loop
|
||||||
|
|
||||||
fn range(from: int, to: int) -> (fn() -> (int, bool)) {
|
x := 0
|
||||||
i := from - 1
|
|
||||||
end := to - 1
|
|
||||||
|
|
||||||
fn() -> (int, bool) {
|
n := 1
|
||||||
if i < end {
|
p := 1
|
||||||
(i = i+1, true)
|
|
||||||
} else {
|
|
||||||
(-1, false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
(a, b) := (0, 1)
|
while x < 100 {
|
||||||
for _ in range(0, 100) {
|
f := n + p
|
||||||
(a, b) = (a + b, a)
|
|
||||||
println(a)
|
p = n
|
||||||
|
n = f
|
||||||
|
|
||||||
|
write(f)
|
||||||
|
x = x + 1
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
|
|
||||||
fn sum(a: int, b: int) -> int {
|
func sum(a, b) {
|
||||||
a + b
|
return a + b
|
||||||
}
|
}
|
||||||
|
|
||||||
println(sum(1, 2))
|
write(sum(1, 2))
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
fn f(x) {
|
func f(x) {
|
||||||
return x*x - 4
|
return x*x - 4
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
|
|
||||||
println("Hello world!")
|
write("Hello world!")
|
||||||
|
|
||||||
a := 1 + 2
|
a := 1 + 2
|
||||||
println(a)
|
|
||||||
|
write(a)
|
||||||
|
|
||||||
|
|
||||||
if a > 2 {
|
if a > 2 {
|
||||||
println("Hooray!! a is greater than 2!!!!")
|
write("Hooray!! a is greater than 2!!!!")
|
||||||
} else {
|
} else {
|
||||||
println("oh nooo!!! a is less than or equal to 2!!!!!!!!!!")
|
write("oh nooo!!! a is less than or equal to 2!!!!!!!!!!")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
import "math.ang"
|
import "math.ang"
|
||||||
|
|
||||||
println(sqrt(2.0))
|
write(sqrt(2))
|
||||||
|
|
|
||||||
|
|
@ -1,47 +1,51 @@
|
||||||
|
|
||||||
# Empty list
|
# Empty list
|
||||||
println([])
|
write([])
|
||||||
|
|
||||||
# List with items
|
# List with items
|
||||||
println([3, 1, 4, 1, 5, 9, 2, 6, 5])
|
write([3, 1, 4, 1, 5, 9, 2, 6, 5])
|
||||||
|
|
||||||
# List with items of different types
|
# List with items of different types
|
||||||
println(["", "私はかっこいいです。", true, nil, nil, 1, 2])
|
write(["", "私はかっこいいです。", true, nil, nil, 1, 2])
|
||||||
|
|
||||||
a := []
|
a := []
|
||||||
|
|
||||||
a = a + [1]
|
a = a.append(1)
|
||||||
a = a + [2]
|
a = a.append(2)
|
||||||
|
|
||||||
println(a)
|
write(a)
|
||||||
|
|
||||||
|
|
||||||
list := []
|
list := []
|
||||||
|
|
||||||
|
n := 0
|
||||||
x := 0
|
x := 0
|
||||||
for n in 0..100 {
|
while n < 100 {
|
||||||
x = x + 2*n + 1
|
x = x + 2*n + 1
|
||||||
|
|
||||||
list = list + [x]
|
list = list.append(x)
|
||||||
|
n = n + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
println(list)
|
write(list)
|
||||||
println(list.map(func(a) {
|
write(list.map(func(a) {
|
||||||
return a - 1
|
return a - 1
|
||||||
}))
|
}))
|
||||||
println(list.length())
|
write(list.length())
|
||||||
println(list.at(69))
|
write(list.at(69))
|
||||||
|
|
||||||
other := []
|
other := []
|
||||||
|
|
||||||
for a in 0..=10 {
|
a := 1
|
||||||
|
while a <= 10 {
|
||||||
other = other.append(a)
|
other = other.append(a)
|
||||||
|
a = a + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
sum := other.reduce(func(tot, x) {
|
sum := other.reduce(func(tot, x) {
|
||||||
return tot + x
|
return tot + x
|
||||||
}, 0)
|
}, 0)
|
||||||
|
|
||||||
println(sum)
|
write(sum)
|
||||||
|
|
||||||
assert(sum == a*(a-1)/2)
|
assert(sum == a*(a-1)/2)
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,9 @@ tot = tot * 6.0
|
||||||
# get the absolute value of a number
|
# get the absolute value of a number
|
||||||
fn abs(x: float) -> float {
|
fn abs(x: float) -> float {
|
||||||
if x < 0.0 {
|
if x < 0.0 {
|
||||||
-x
|
return -x
|
||||||
} else {
|
|
||||||
x
|
|
||||||
}
|
}
|
||||||
|
return x
|
||||||
}
|
}
|
||||||
|
|
||||||
# calculate an approximation of the square root of tot using
|
# calculate an approximation of the square root of tot using
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,16 @@
|
||||||
import "math.ang"
|
import "math.ang"
|
||||||
|
|
||||||
fn r_x(t: float) -> float {
|
func r_x(t) {
|
||||||
return 8.0*(exp(-t) - t)
|
return 8*(exp(-t) - t)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn r_y(t: float) -> float {
|
func r_y(t) {
|
||||||
return 5.0*(exp(-t) - t)
|
return 5*(exp(-t) - t)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn r(t: float) -> (float, float) {
|
func r(t) {
|
||||||
return (r_x(t), r_y(t))
|
return format("(%s, %s)", [r_x(t), r_y(t)])
|
||||||
}
|
}
|
||||||
|
|
||||||
println(r(1.0))
|
write(r(1))
|
||||||
|
write()
|
||||||
|
|
|
||||||
4
fails.ang
Normal file
4
fails.ang
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
import "lib/honning.ang"
|
||||||
|
|
||||||
|
write(_bell+_italic+"Hello "+_underline+"world "+_strike+"micheal"+_reset)
|
||||||
|
|
||||||
15
imp.ang
Normal file
15
imp.ang
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
|
||||||
|
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)))
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
fn (l: list) map(list: [any], f: fn(any) -> any) -> [any] {
|
fn map(list: [any], f: fn(any) -> any) -> [any] {
|
||||||
out := []
|
out := []
|
||||||
|
|
||||||
i := 0
|
i := 0
|
||||||
|
|
|
||||||
50
lib/math.ang
50
lib/math.ang
|
|
@ -9,7 +9,7 @@ E := 2.718281828459045235360287471352
|
||||||
# returned value is x.
|
# returned value is x.
|
||||||
fn absf(x: float) -> float {
|
fn absf(x: float) -> float {
|
||||||
# if the number is negative
|
# if the number is negative
|
||||||
if x < 0.0 {
|
if x < 0 {
|
||||||
# negate it so it's positive
|
# negate it so it's positive
|
||||||
return -x
|
return -x
|
||||||
}
|
}
|
||||||
|
|
@ -26,7 +26,7 @@ fn absi(n: int) -> int {
|
||||||
}
|
}
|
||||||
|
|
||||||
DERIVE_DX := 0.00000001
|
DERIVE_DX := 0.00000001
|
||||||
fn derive(f: fn(float) -> float, x: float) -> float {
|
fn derive(f: fn(float) -> float, x: float) float {
|
||||||
return (f(x + DERIVE_DX) - f(x))/DERIVE_DX
|
return (f(x + DERIVE_DX) - f(x))/DERIVE_DX
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -35,7 +35,7 @@ fn newtons(f: fn(float) -> float) -> float {
|
||||||
pg := 0.0
|
pg := 0.0
|
||||||
g := 1.0
|
g := 1.0
|
||||||
|
|
||||||
while absf(g - pg) > NEWTONS_ACC {
|
while abs(g - pg) > NEWTONS_ACC {
|
||||||
pg = g
|
pg = g
|
||||||
g = pg - f(pg) / derive(f, pg)
|
g = pg - f(pg) / derive(f, pg)
|
||||||
}
|
}
|
||||||
|
|
@ -53,14 +53,12 @@ fn sqrt(x: float) -> float {
|
||||||
ng := x
|
ng := x
|
||||||
g := 1.0
|
g := 1.0
|
||||||
|
|
||||||
while absf(g - ng) > MAX_SQRT_DX {
|
while abs(g - ng) > MAX_SQRT_DX {
|
||||||
g = ng
|
g = ng
|
||||||
|
|
||||||
# create new guess
|
# create new guess
|
||||||
ng = (g + x / g) / 2.0
|
ng = (g + x / g) / 2
|
||||||
}
|
}
|
||||||
|
|
||||||
g
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# floor(x)
|
# floor(x)
|
||||||
|
|
@ -84,7 +82,7 @@ fn round(x: float) -> float {
|
||||||
f := floor(x)
|
f := floor(x)
|
||||||
|
|
||||||
if x - f > 0.5 {
|
if x - f > 0.5 {
|
||||||
return f + 1.0
|
return f + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
return f
|
return f
|
||||||
|
|
@ -95,16 +93,16 @@ fn round(x: float) -> float {
|
||||||
# n: number; the number to divide by
|
# n: number; the number to divide by
|
||||||
# Return the rest from a division of x by n.
|
# Return the rest from a division of x by n.
|
||||||
fn mod(x: float, n: float) -> float {
|
fn mod(x: float, n: float) -> float {
|
||||||
if x == 0.0 {
|
if x == 0 {
|
||||||
return 0.0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
if x < 0.0 {
|
if x < 0 {
|
||||||
while x + n <= 0.0 {
|
while x + n <= 0 {
|
||||||
x = x + n
|
x = x + n
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
while x - n >= 0.0 {
|
while x - n >= 0 {
|
||||||
x = x - n
|
x = x - n
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -125,7 +123,7 @@ fn sm_exp(x: float) -> float {
|
||||||
x_pow := x
|
x_pow := x
|
||||||
f := 1.0
|
f := 1.0
|
||||||
|
|
||||||
while absf(tot - p_tot) > SM_EXP_ACC {
|
while abs(tot - p_tot) > SM_EXP_ACC {
|
||||||
p_tot = tot
|
p_tot = tot
|
||||||
t := x_pow / f
|
t := x_pow / f
|
||||||
tot = tot + t
|
tot = tot + t
|
||||||
|
|
@ -141,18 +139,18 @@ fn sm_exp(x: float) -> float {
|
||||||
# x: number; any number
|
# x: number; any number
|
||||||
# Get an approximate value of e raised to the power of x.
|
# Get an approximate value of e raised to the power of x.
|
||||||
fn exp(x: float) -> float {
|
fn exp(x: float) -> float {
|
||||||
n := absf(x)
|
n := abs(x)
|
||||||
tot := 1.0
|
tot := 1.0
|
||||||
while n >= 1.0 {
|
while n >= 1 {
|
||||||
tot = tot * E
|
tot = tot * E
|
||||||
n = n - 1.0
|
n = n - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if n > 0.0 {
|
if n > 0.0 {
|
||||||
tot = tot * sm_exp(n)
|
tot = tot * sm_exp(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
if x < 0.0 {
|
if x < 0 {
|
||||||
1.0/tot
|
1.0/tot
|
||||||
} else {
|
} else {
|
||||||
tot
|
tot
|
||||||
|
|
@ -168,9 +166,9 @@ fn ln(x: float) -> float {
|
||||||
pg := 0.0
|
pg := 0.0
|
||||||
g := 1.0
|
g := 1.0
|
||||||
|
|
||||||
while absf(pg - g) > LN_ACC {
|
while abs(pg - g) > LN_ACC {
|
||||||
pg = g
|
pg = g
|
||||||
g = pg + x / exp(pg) - 1.0
|
g = pg + x / exp(pg) - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
return g
|
return g
|
||||||
|
|
@ -196,7 +194,7 @@ fn log(a: float, b: float) -> float {
|
||||||
pg := 0.0
|
pg := 0.0
|
||||||
g := 1.0
|
g := 1.0
|
||||||
|
|
||||||
while absf(g - pg) > LOG_ACC {
|
while abs(g - pg) > LOG_ACC {
|
||||||
pg = g
|
pg = g
|
||||||
g = pg - 1.0/ln_b - a/(ln_b*pow(b, pg))
|
g = pg - 1.0/ln_b - a/(ln_b*pow(b, pg))
|
||||||
}
|
}
|
||||||
|
|
@ -213,7 +211,7 @@ fn sin(x: float) -> float {
|
||||||
x = mod(x, 2.0*PI)
|
x = mod(x, 2.0*PI)
|
||||||
if x > PI {
|
if x > PI {
|
||||||
x = PI - x
|
x = PI - x
|
||||||
f = -1.0
|
f = -1
|
||||||
}
|
}
|
||||||
|
|
||||||
# compute sine with a taylor series mock function of sine (valid between -pi and +pi)
|
# compute sine with a taylor series mock function of sine (valid between -pi and +pi)
|
||||||
|
|
@ -222,7 +220,7 @@ fn sin(x: float) -> float {
|
||||||
i := 1.0
|
i := 1.0
|
||||||
s := -1.0
|
s := -1.0
|
||||||
|
|
||||||
while i <= 19.0 {
|
while i <= 19 {
|
||||||
i = i + 2.0
|
i = i + 2.0
|
||||||
l = s * l * x / i / (i-1.0)
|
l = s * l * x / i / (i-1.0)
|
||||||
|
|
||||||
|
|
@ -237,15 +235,13 @@ fn sin(x: float) -> float {
|
||||||
# cos(x)
|
# cos(x)
|
||||||
# x: number; an angle in radians
|
# x: number; an angle in radians
|
||||||
# Get the cosine of an angle (in radians). https://en.wikipedia.org/wiki/Sine_and_cosine
|
# Get the cosine of an angle (in radians). https://en.wikipedia.org/wiki/Sine_and_cosine
|
||||||
fn cos(x: float) -> float {
|
func cos(x: number) number {
|
||||||
# todo
|
# todo
|
||||||
0.0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# tan(x)
|
# tan(x)
|
||||||
# x: number; an angle in radians
|
# x: number; an angle in radians
|
||||||
# Get the tangent of an angle. https://en.wikipedia.org/wiki/Tangent
|
# Get the tangent of an angle. https://en.wikipedia.org/wiki/Tangent
|
||||||
fn tan(x: float) -> float {
|
func tan(x: number) number {
|
||||||
# todo
|
# todo
|
||||||
0.0
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
|
|
||||||
assertEq((1, 2), (1, 2))
|
|
||||||
|
|
||||||
assertEq(typeof((1,)), typeof((1,)))
|
|
||||||
assertEq((1,), (1,))
|
|
||||||
|
|
||||||
fn neighbours(n: int) -> (int, int) {
|
|
||||||
(n-1, n+1)
|
|
||||||
}
|
|
||||||
|
|
||||||
assertEq(neighbours(2), (1, 3))
|
|
||||||
|
|
@ -1,15 +1,8 @@
|
||||||
|
|
||||||
assertEq(typeof(1), "int")
|
assertEq(type(1), "int")
|
||||||
assertEq(typeof("Hello"), "string")
|
assertEq(type("Hello"), "string")
|
||||||
assertEq(typeof(true), "boolean")
|
assertEq(type(true), "boolean")
|
||||||
|
|
||||||
# lists
|
# lists
|
||||||
assertEq(typeof(["Hello", "world"]), "[string]")
|
assertEq(type(["Hello", "world"]), "list[string]")
|
||||||
assertEq(typeof([0, 1]), "[int]")
|
assertEq(type([0, 1]), "list[int]")
|
||||||
assertEq(typeof((0, 1)), "(int, int)")
|
|
||||||
|
|
||||||
type Vec2 = (int, int)
|
|
||||||
|
|
||||||
fn add(a: Vec2, b: Vec2) -> Vec2 {
|
|
||||||
(a[0] + b[0], a[1] + b[1])
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
|
|
||||||
build:
|
|
||||||
GOOS=js GOARCH=wasm go build .
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue