Skip to content

Commit

Permalink
feat: init signature #37
Browse files Browse the repository at this point in the history
  • Loading branch information
JohnCoene committed Sep 7, 2024
1 parent 20d76bc commit 5f00672
Show file tree
Hide file tree
Showing 11 changed files with 435 additions and 4 deletions.
23 changes: 23 additions & 0 deletions ast/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,29 @@ func (types Types) String() string {
return strings.Join(strs, ", ")
}

type TypeFunction struct {
Token token.Item // type token
Name string
Arguments []Types
Return Types
}

func (tf *TypeFunction) Item() token.Item { return tf.Token }
func (tf *TypeFunction) statementNode() {}
func (tf *TypeFunction) TokenLiteral() string { return tf.Token.Value }
func (tf *TypeFunction) String() string {
var out bytes.Buffer

out.WriteString("# function type ")
out.WriteString(tf.Name)

for _, a := range tf.Arguments {
out.WriteString("# " + a.String())
}

return out.String()
}

type TypeStatement struct {
Token token.Item // type token
Name string
Expand Down
29 changes: 29 additions & 0 deletions environment/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ type Environment struct {
class map[string]Class
matrix map[string]Matrix
factor map[string]Factor
signature map[string]Signature
returnType ast.Types
outer *Environment
}
Expand Down Expand Up @@ -68,6 +69,7 @@ func New() *Environment {
f := make(map[string]Function)
c := make(map[string]Class)
m := make(map[string]Matrix)
s := make(map[string]Signature)
fct := make(map[string]Factor)

env := &Environment{
Expand All @@ -76,6 +78,7 @@ func New() *Environment {
types: t,
class: c,
matrix: m,
signature: s,
factor: fct,
outer: nil,
}
Expand Down Expand Up @@ -104,6 +107,19 @@ func New() *Environment {
return env
}

func (e *Environment) SetSignatureUsed(name string) (Signature, bool) {
obj, ok := e.signature[name]

if !ok && e.outer != nil {
return e.outer.SetSignatureUsed(name)
}

obj.Used = true
e.signature[name] = obj

return obj, ok
}

func (e *Environment) SetTypeUsed(name string) (Type, bool) {
obj, ok := e.types[name]

Expand Down Expand Up @@ -218,6 +234,19 @@ func (e *Environment) SetFactor(name string, val Factor) Factor {
return val
}

func (e *Environment) GetSignature(name string) (Signature, bool) {
obj, ok := e.signature[name]
if !ok && e.outer != nil {
obj, ok = e.outer.GetSignature(name)
}
return obj, ok
}

func (e *Environment) SetSignature(name string, val Signature) Signature {
e.signature[name] = val
return val
}

func (e *Environment) GetMatrix(name string) (Matrix, bool) {
obj, ok := e.matrix[name]
if !ok && e.outer != nil {
Expand Down
6 changes: 6 additions & 0 deletions environment/object.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,9 @@ type Factor struct {
Token token.Item
Value *ast.DecoratorFactor
}

type Signature struct {
Token token.Item
Value *ast.TypeFunction
Used bool
}
45 changes: 45 additions & 0 deletions lexer/lex.go
Original file line number Diff line number Diff line change
Expand Up @@ -932,11 +932,56 @@ func lexTypeDeclaration(l *Lexer) stateFn {
return lexStruct
}

if tok == "func" {
l.emit(token.ItemObjFunc)
return lexFuncSignature
}

l.emit(token.ItemTypes)

return lexType
}

func lexFuncSignature(l *Lexer) stateFn {
if l.peek(1) != '(' {
l.errorf("expecting `(`, got `%c`", l.peek(1))
}

l.next()
l.emit(token.ItemLeftParen)

return lexFuncSignatureArg
}

func lexFuncSignatureArg(l *Lexer) stateFn {
if l.peek(1) == '[' {
l.next()
l.next()
l.emit(token.ItemTypesList)
}

l.acceptRun(stringAlpha)
l.emit(token.ItemTypes)

if l.peek(1) == ',' {
l.next()
l.emit(token.ItemComma)
if l.peek(1) == ' ' {
l.next()
l.ignore()
}
return lexFuncSignatureArg
}

if l.peek(1) == ')' {
l.next()
l.emit(token.ItemRightParen)
return lexType
}

return lexDefault
}

func lexStruct(l *Lexer) stateFn {
if l.peek(1) == ' ' {
l.next()
Expand Down
39 changes: 39 additions & 0 deletions lexer/lex_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -471,3 +471,42 @@ x += 1
}
}
}

func TestFuncType(t *testing.T) {
code := `type fn: func(int, []num) int`

l := NewTest(code)

l.Run()

if len(l.Items) == 0 {
t.Fatal("No Items where lexed")
}

tokens :=
[]token.ItemType{
token.ItemTypesDecl,
token.ItemTypes,
token.ItemColon,
token.ItemObjFunc,
token.ItemLeftParen,
token.ItemTypes,
token.ItemComma,
token.ItemTypesList,
token.ItemTypes,
token.ItemRightParen,
token.ItemTypes,
}

for i, token := range tokens {
actual := l.Items[i].Class
if actual != token {
t.Fatalf(
"token %v expected `%v`, got `%v`",
i,
token,
actual,
)
}
}
}
53 changes: 52 additions & 1 deletion parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ func (p *Parser) parseStatement() ast.Statement {
case token.ItemNewLine:
return p.parseNewLine()
case token.ItemTypesDecl:
return p.parseTypeDeclaration()
return p.parseTypeDeclarations()
default:
return p.parseExpressionStatement()
}
Expand Down Expand Up @@ -405,6 +405,57 @@ func (p *Parser) parseInf() ast.Expression {
}
}

func (p *Parser) parseTypeDeclarations() ast.Statement {
p.nextToken()
p.nextToken()
if p.peekToken.Value == "func" {
p.previousToken(2)
return p.parseTypeDeclarationFunc()
}
p.previousToken(2)
return p.parseTypeDeclaration()
}

func (p *Parser) parseTypeDeclarationFunc() *ast.TypeFunction {
fn := &ast.TypeFunction{
Token: p.curToken,
}

// expect the custom type
if !p.expectPeek(token.ItemTypes) {
return nil
}

fn.Name = p.curToken.Value

if !p.expectPeek(token.ItemColon) {
return nil
}

p.nextToken()

if !p.expectPeek(token.ItemLeftParen) {
return nil
}

for !p.peekTokenIs(token.ItemRightParen) {
fn.Arguments = append(fn.Arguments, p.parseTypes())
if p.peekTokenIs(token.ItemComma) {
p.nextToken()
}
}

if !p.expectPeek(token.ItemRightParen) {
return nil
}

p.nextToken()

fn.Return = p.parseTypes()

return fn
}

func (p *Parser) parseTypeDeclaration() *ast.TypeStatement {
typ := &ast.TypeStatement{
Token: p.curToken,
Expand Down
38 changes: 38 additions & 0 deletions parser/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -663,3 +663,41 @@ let types: any = strsplit(parts[2], "\\|")[[1]]

fmt.Println(prog.String())
}

func TestFuncType(t *testing.T) {
fmt.Println("----------------------------- type")
code := `
type math: func(int, int) int
func apply_math(x: int = 2, y: int = 2, cb: math): int {
return cb(x, y)
}
func multiply(x: int = 2, y: int = 1): int {
return x * y
}
apply_math(1, 2, multiply)
apply_math(1, 2, (x: int, y: int) => {
return x + y
})
func bar(): math {
return multiply
}
let x: math = bar()
`

l := lexer.NewTest(code)

l.Run()
p := New(l)

prog := p.Run()

p.Errors().Print()

fmt.Println(prog.String())
}
3 changes: 2 additions & 1 deletion token/print.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,12 @@ var ItemName = map[ItemType]string{
ItemDecoratorDefault: "decorator default",
ItemAttribute: "attribute",
ItemObjList: "object list",
ItemObjFunc: "object function",
ItemObjDataframe: "object dataframe",
ItemObjStruct: "object struct",
ItemObjObject: "object object",
ItemObjMatrix: "object matrix",
ItemObjFunc: "object func",
ItemObjFactor: "object factor",
}

func (t ItemType) String() string {
Expand Down
Loading

0 comments on commit 5f00672

Please sign in to comment.