Skip to content

Commit

Permalink
feat: (WIP) support parapoly with $ sign
Browse files Browse the repository at this point in the history
  • Loading branch information
nawetimebomb committed Sep 29, 2024
1 parent 59a6657 commit 3738ee5
Show file tree
Hide file tree
Showing 4 changed files with 176 additions and 116 deletions.
178 changes: 92 additions & 86 deletions compiler/frontend.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,21 +215,7 @@ func registerFunction(token Token) {
if !check(TOKEN_RIGHT_ARROW) && !check(TOKEN_PAREN_OPEN) {
for !check(TOKEN_RIGHT_ARROW) && !check(TOKEN_PAREN_OPEN) && !check(TOKEN_EOF) {
advance()
t := parser.previous
targ := DATA_EMPTY

switch t.typ {
case TOKEN_DTYPE_BOOL: targ = DATA_BOOL
case TOKEN_DTYPE_CHAR: targ = DATA_CHAR
case TOKEN_DTYPE_INT: targ = DATA_INT
case TOKEN_DTYPE_PTR: targ = DATA_PTR
default:
msg := fmt.Sprintf(MsgParseTypeUnknown, t.value)
errorAt(&t, msg)
ExitWithError(CodeParseError)
}

function.args = append(function.args, targ)
parseArityInFunction(parser.previous, &function, "argument")
}
}

Expand All @@ -240,21 +226,7 @@ func registerFunction(token Token) {

for !check(TOKEN_PAREN_OPEN) {
advance()
t := parser.previous
tret := DATA_EMPTY

switch t.typ {
case TOKEN_DTYPE_BOOL: tret = DATA_BOOL
case TOKEN_DTYPE_CHAR: tret = DATA_CHAR
case TOKEN_DTYPE_INT: tret = DATA_INT
case TOKEN_DTYPE_PTR: tret = DATA_PTR
default:
msg := fmt.Sprintf(MsgParseTypeUnknown, t.value)
errorAt(&t, msg)
ExitWithError(CodeParseError)
}

function.rets = append(function.rets, tret)
parseArityInFunction(parser.previous, &function, "return")
}
}

Expand Down Expand Up @@ -470,42 +442,13 @@ func addExtern(token Token) {

for !check(TOKEN_RIGHT_ARROW) && !check(TOKEN_PAREN_OPEN) && !check(TOKEN_EOF) {
advance()
var arg DataType
t := parser.previous

switch t.typ {
case TOKEN_DTYPE_BOOL: arg = DATA_BOOL
case TOKEN_DTYPE_CHAR: arg = DATA_CHAR
case TOKEN_DTYPE_INT: arg = DATA_INT
case TOKEN_DTYPE_PTR: arg = DATA_PTR
default:
msg := fmt.Sprintf(MsgParseTypeUnknown, t.value)
errorAt(&t, msg)
ExitWithError(CodeParseError)
}

value.args = append(value.args, arg)
parseArityInAssembly(parser.previous, &value.arguments)
}

if match(TOKEN_RIGHT_ARROW) {
for !check(TOKEN_PAREN_OPEN) && !check(TOKEN_EOF) {
advance()
var arg DataType

t := parser.previous

switch t.typ {
case TOKEN_DTYPE_BOOL: arg = DATA_BOOL
case TOKEN_DTYPE_CHAR: arg = DATA_CHAR
case TOKEN_DTYPE_INT: arg = DATA_INT
case TOKEN_DTYPE_PTR: arg = DATA_PTR
default:
msg := fmt.Sprintf(MsgParseTypeUnknown, t.value)
errorAt(&t, msg)
ExitWithError(CodeParseError)
}

value.rets = append(value.rets, arg)
parseArityInAssembly(parser.previous, &value.returns)
}
}

Expand Down Expand Up @@ -745,46 +688,109 @@ func parseToken(token Token) {
}
}

func parseArityInAssembly(token Token, args *Arity) {
var newArg Argument

switch token.typ {
case TOKEN_DTYPE_BOOL:
newArg.typ = DATA_BOOL
case TOKEN_DTYPE_CHAR:
newArg.typ = DATA_CHAR
case TOKEN_DTYPE_INT:
newArg.typ = DATA_INT
case TOKEN_DTYPE_PTR:
newArg.typ = DATA_PTR
default:
msg := fmt.Sprintf(MsgParseTypeUnknown, token.value.(string))
errorAt(&token, msg)
ExitWithError(CodeParseError)
}

args.types = append(args.types, newArg)
}

func parseArityInFunction(token Token, function *Function, parsing string) {
var newArg Argument

parsingArguments := parsing == "argument"

switch token.typ {
case TOKEN_DTYPE_ANY:
if !parser.internal {
errorAt(&token, "TODO: ERROR MESSAGE. CANT USE ANY IN CUSTOM CODE")
ExitWithError(CodeParseError)
}

newArg.typ = DATA_ANY
case TOKEN_DTYPE_BOOL:
newArg.typ = DATA_BOOL
case TOKEN_DTYPE_CHAR:
newArg.typ = DATA_CHAR
case TOKEN_DTYPE_INT:
newArg.typ = DATA_INT
case TOKEN_DTYPE_PTR:
newArg.typ = DATA_PTR
case TOKEN_DTYPE_PARAPOLY:
if !parsingArguments {
errorAt(&token, "TODO: CANT USE THIS TYPE IN RETURNS")
ExitWithError(CodeParseError)
}

newArg.typ = DATA_INFER
newArg.name = token.value.(string)
function.arguments.parapoly = true
case TOKEN_WORD:
w := token.value.(string)

if parsingArguments {
msg := fmt.Sprintf(MsgParseTypeUnknown, w)
errorAt(&token, msg)
ExitWithError(CodeParseError)
}

funcArgs := function.arguments
argTest := Argument{name: w, typ: DATA_INFER}

if funcArgs.parapoly && Contains(funcArgs.types, argTest) {
newArg.typ = DATA_INFER
newArg.name = token.value.(string)
function.returns.parapoly = true
} else {
errorAt(&token, "TODO: Definition for this type doesn't exist")
ExitWithError(CodeParseError)
}
default:
msg := fmt.Sprintf(MsgParseTypeUnknown, token.value.(string))
errorAt(&token, msg)
ExitWithError(CodeParseError)
}

if parsingArguments {
function.arguments.types = append(function.arguments.types, newArg)
} else {
function.returns.types = append(function.returns.types, newArg)
}
}

func parseFunction(token Token) {
// Recreate a temporary function entry to match with the already registered
// function in TheProgram. That's why this step doesn't have any error checking.
var testFunc Function

advance()

testFunc.name = parser.previous.value.(string)

if !check(TOKEN_RIGHT_ARROW) && !check(TOKEN_PAREN_OPEN) {
for !check(TOKEN_RIGHT_ARROW) && !check(TOKEN_PAREN_OPEN) && !check(TOKEN_EOF) {
advance()
t := parser.previous
targ := DATA_EMPTY

switch t.typ {
case TOKEN_DTYPE_BOOL: targ = DATA_BOOL
case TOKEN_DTYPE_CHAR: targ = DATA_CHAR
case TOKEN_DTYPE_INT: targ = DATA_INT
case TOKEN_DTYPE_PTR: targ = DATA_PTR
}

testFunc.args = append(testFunc.args, targ)
parseArityInFunction(parser.previous, &testFunc, "argument")
}
}

if match(TOKEN_RIGHT_ARROW) {
for !check(TOKEN_PAREN_OPEN) {
advance()
t := parser.previous
tret := DATA_EMPTY

switch t.typ {
case TOKEN_DTYPE_BOOL: tret = DATA_BOOL
case TOKEN_DTYPE_CHAR: tret = DATA_CHAR
case TOKEN_DTYPE_INT: tret = DATA_INT
case TOKEN_DTYPE_PTR: tret = DATA_PTR
}

testFunc.rets = append(testFunc.rets, tret)
parseArityInFunction(parser.previous, &testFunc, "return")
}
}

Expand All @@ -795,8 +801,8 @@ func parseFunction(token Token) {
// and the returns.
for index, f := range TheProgram.chunks {
if !f.parsed && f.name == testFunc.name &&
reflect.DeepEqual(f.args, testFunc.args) &&
reflect.DeepEqual(f.rets, testFunc.rets) {
reflect.DeepEqual(f.arguments, testFunc.arguments) &&
reflect.DeepEqual(f.returns, testFunc.returns) {
frontend.current = &TheProgram.chunks[index]
break
}
Expand Down
25 changes: 18 additions & 7 deletions compiler/ir.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,13 @@ const (
type DataType int

const (
DATA_EMPTY DataType = iota
DATA_NONE DataType = iota
DATA_ANY
DATA_BOOL
DATA_CHAR
DATA_INFER
DATA_INT
DATA_PTR
DATA_ANY
)

type Bound struct {
Expand All @@ -74,23 +75,33 @@ type Program struct {
variables []Object
}

type Argument struct {
name string
typ DataType
}

type Arity struct {
parapoly bool
types []Argument
}

type Function struct {
ip int
name string
arguments Arity
returns Arity
loc Location
bindings []Bound
args []DataType
rets []DataType
code []Code
parsed bool
called bool
internal bool
}

type Extern struct {
args []DataType
body []string
rets []DataType
arguments Arity
returns Arity
body []string
}

type Code struct {
Expand Down
15 changes: 15 additions & 0 deletions compiler/scanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ const (
TOKEN_TRUE

// Types
TOKEN_DTYPE_ANY
TOKEN_DTYPE_BOOL
TOKEN_DTYPE_CHAR
TOKEN_DTYPE_INT
TOKEN_DTYPE_PARAPOLY
TOKEN_DTYPE_PTR

// Reserved Words
Expand Down Expand Up @@ -90,6 +92,7 @@ var reservedWords = []reserved{
reserved{typ: TOKEN_CONST, word: "const" },
reserved{typ: TOKEN_DIV, word: "div" },
reserved{typ: TOKEN_DROP, word: "drop" },
reserved{typ: TOKEN_DTYPE_ANY, word: "any" },
reserved{typ: TOKEN_DTYPE_BOOL, word: "bool" },
reserved{typ: TOKEN_DTYPE_CHAR, word: "char" },
reserved{typ: TOKEN_DTYPE_INT, word: "int" },
Expand Down Expand Up @@ -254,6 +257,16 @@ func makeWord(c byte, line string, index *int) {
makeToken(TOKEN_WORD, word)
}

func makeParapolyToken(c byte, line string, index *int) {
word := ""

for Advance(&c, line, index) && !IsSpace(c) {
word += string(c)
}

makeToken(TOKEN_DTYPE_PARAPOLY, word)
}

func TokenizeFile(f string, s string) []Token {
scanner.filename = f
scanner.source = s
Expand All @@ -275,6 +288,8 @@ func TokenizeFile(f string, s string) []Token {
}

switch {
case c == '$':
makeParapolyToken(c, line, &index)
case c == '"':
makeString(c, line, &index)
case c == '\'':
Expand Down
Loading

0 comments on commit 3738ee5

Please sign in to comment.