Skip to content

Commit

Permalink
feat: start adding offset for arrays
Browse files Browse the repository at this point in the history
  • Loading branch information
nawetimebomb committed Oct 17, 2024
1 parent 386ed4b commit 65c316e
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 38 deletions.
2 changes: 1 addition & 1 deletion compiler/codegen.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,8 @@ func generateLinuxX64() {

// NUMBER ARITHMETICS
case OP_ADD:
out.WriteCode(" pop rax")
out.WriteCode(" pop rbx")
out.WriteCode(" pop rax")
out.WriteCode(" add rax, rbx")
out.WriteCode(" push rax")
case OP_DIVIDE:
Expand Down
70 changes: 51 additions & 19 deletions compiler/frontend.go
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,9 @@ func createConstant() {

if isWordInUse(wordT) {
if isParsingFunction() {
TheProgram.saveErrorAtToken(wordT, DeclarationWordAlreadyUsed, newConst.word)
TheProgram.saveErrorAtToken(
wordT, DeclarationWordAlreadyUsed, newConst.word,
)
} else {
ReportErrorAtLocation(
DeclarationWordAlreadyUsed,
Expand Down Expand Up @@ -435,10 +437,14 @@ func createForeigns() {
}

func createVariable() {
var newVar Variable
const SIZE_64b = 8
const SIZE_8b = 1
var currentOffset int
var newOffset int
const SIZE_64b = 8
var newVar Variable
// newOffset is 1 because we multiply it by the size of the type. But it may
// be greater than one if the user is creating an array.
offsetMultiplier := 1

if isParsingFunction() {
currentOffset = parser.currentFn.localMemorySize
Expand All @@ -461,14 +467,12 @@ func createVariable() {
wordT := parser.previousToken
newVar.word = wordT.value.(string)
newVar.offset = currentOffset
// TODO: This should be calculated, not hardcoded. It should take the size
// of the type (next token) and align it to 8 bytes
// formula: size + 7 / 8 * 8
newOffset = currentOffset + SIZE_64b

if isWordInUse(wordT) {
if isParsingFunction() {
TheProgram.saveErrorAtToken(wordT, DeclarationWordAlreadyUsed, newVar.word)
TheProgram.saveErrorAtToken(
wordT, DeclarationWordAlreadyUsed, newVar.word,
)
} else {
ReportErrorAtLocation(
DeclarationWordAlreadyUsed,
Expand All @@ -479,20 +483,29 @@ func createVariable() {
}
}

if match(TOKEN_OFFSET) {
offsetMultiplier = getOffsetValue()
}

advance()
valueT := parser.previousToken

switch valueT.kind {
case TOKEN_BOOL:
newVar.kind = BOOL
newVar.size = SIZE_8b
case TOKEN_BYTE:
newVar.kind = BYTE
newVar.size = SIZE_8b
case TOKEN_INT:
newVar.kind = INT
newVar.size = SIZE_64b
case TOKEN_PTR:
newVar.kind = RAWPOINTER
newVar.size = SIZE_64b
case TOKEN_STR:
newVar.kind = STRING
newVar.size = SIZE_64b
default:
if isParsingFunction() {
TheProgram.saveErrorAtToken(valueT, VariableValueKindNotAllowed)
Expand All @@ -502,13 +515,16 @@ func createVariable() {
}
}

// Formula to calculate total space for the array, aligning it to 8 bytes.
newOffset = int((newVar.size * offsetMultiplier + 7) / 8) * 8

if isParsingFunction() {
parser.currentFn.variables = append(parser.currentFn.variables, newVar)
parser.currentFn.localMemorySize = newOffset
parser.currentFn.localMemorySize += newOffset
} else {
parser.globalWords = append(parser.globalWords, newVar.word)
TheProgram.variables = append(TheProgram.variables, newVar)
TheProgram.staticMemorySize = newOffset
TheProgram.staticMemorySize += newOffset
}
}

Expand Down Expand Up @@ -639,6 +655,20 @@ func getConstant(word string) (*Constant, bool) {
return nil, false
}

func getOffsetValue() int {
var offsetValue int
var err error
t := parser.previousToken

offsetValue, err = strconv.Atoi(t.value.(string))

if err != nil {
// TODO: Check for value in variables
}

return offsetValue
}

func getVariable(word string) (*Variable, bool) {
if isParsingFunction() {
for _, v := range parser.currentFn.variables {
Expand Down Expand Up @@ -735,6 +765,12 @@ func parseToken() {
}
code.value = v.offset
emit(code)

if match(TOKEN_OFFSET) {
offset := getOffsetValue()
emit(Code{op: OP_PUSH_INT, value: offset * v.size})
emit(Code{op: OP_ADD})
}
}

// TYPE CASTING
Expand Down Expand Up @@ -801,10 +837,6 @@ func parseToken() {

for i, t := range body {
switch t.kind {
case TOKEN_BRACKET_CLOSE:
line = append(line, "]")
case TOKEN_BRACKET_OPEN:
line = append(line, "[")
case TOKEN_CONSTANT_INT:
line = append(line, strconv.Itoa(t.value.(int)))
case TOKEN_WORD:
Expand Down Expand Up @@ -912,7 +944,6 @@ func parseToken() {
case TOKEN_BANG_BYTE:
code.op = OP_STORE_BYTE
emit(code)

// Special
case TOKEN_WORD: expandWord(token)

Expand Down Expand Up @@ -1096,7 +1127,7 @@ func parseArityInFunction(token Token, function *Function, parsingArguments bool
ExitWithError(CodeParseError)
}
default:
msg := fmt.Sprintf(MsgParseTypeUnknown, token.value.(string))
msg := fmt.Sprintf(MsgParseTypeUnknown, token.value)
errorAt(&token, msg)
ExitWithError(CodeParseError)
}
Expand Down Expand Up @@ -1176,8 +1207,7 @@ func compilationFirstPass(index int) {

switch token.kind {
// The second pass will care about the following tokens:
case TOKEN_CONST:
createConstant()
case TOKEN_CONST: createConstant()
case TOKEN_FN:
registerFunction(token)
case TOKEN_FOREIGN:
Expand Down Expand Up @@ -1218,7 +1248,9 @@ func compilationSecondPass(index int) {

switch token.kind {
case TOKEN_FOREIGN:
for !match(TOKEN_BRACKET_CLOSE) && !check(TOKEN_EOF) { advance() }
for !match(TOKEN_CURLY_BRACKET_CLOSE) {
advance()
}
case TOKEN_FN:
parseFunction(token)
}
Expand Down
1 change: 1 addition & 0 deletions compiler/ir.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ type Variable struct {
kind ValueKind
offset int
scope ScopeName
size int
word string
}

Expand Down
31 changes: 17 additions & 14 deletions compiler/scanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,11 @@ const (
TOKEN_AMPERSAND

// Single characters
TOKEN_BRACKET_CLOSE
TOKEN_BRACKET_OPEN
TOKEN_PAREN_CLOSE
TOKEN_PAREN_OPEN

// NEW
TOKEN_OFFSET
TOKEN_DASH_DASH_DASH
TOKEN_LET
TOKEN_IN
Expand Down Expand Up @@ -320,6 +319,16 @@ func makeParapolyToken(c byte, line string, index *int) {
makeToken(TOKEN_PARAPOLY, word)
}

func makeOffsetToken(c byte, line string, index *int) {
value := ""

for Advance(&c, line, index) && c != ']' {
value += string(c)
}

makeToken(TOKEN_OFFSET, value)
}

func TokenizeFile(f string, s string) []Token {
scanner.filename = f
scanner.source = s
Expand All @@ -343,21 +352,15 @@ func TokenizeFile(f string, s string) []Token {
switch {
case c == '{': makeToken(TOKEN_CURLY_BRACKET_OPEN)
case c == '}': makeToken(TOKEN_CURLY_BRACKET_CLOSE)
case c == '[': makeToken(TOKEN_BRACKET_OPEN)
case c == ']': makeToken(TOKEN_BRACKET_CLOSE)
case c == '[': makeOffsetToken(c, line, &index)
case c == '(': makeToken(TOKEN_PAREN_OPEN)
case c == ')': makeToken(TOKEN_PAREN_CLOSE)
case c == '&': makeWord(c, line, &index)
case c == '$':
makeParapolyToken(c, line, &index)
case c == '"':
makeString(c, line, &index)
case c == '\'':
makeChar(c, line, &index)
case IsDigit(c):
makeNumber(c, line, &index)
default:
makeWord(c, line, &index)
case c == '$': makeParapolyToken(c, line, &index)
case c == '"': makeString(c, line, &index)
case c == '\'': makeChar(c, line, &index)
case IsDigit(c): makeNumber(c, line, &index)
default: makeWord(c, line, &index)
}
}

Expand Down
9 changes: 5 additions & 4 deletions libs/libc.sk
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@
; size bigger. 'libc' is linked statically.

foreign c {
fn exit (int) ...
fn fprintf (int any str) ...
fn printf (any str) ...
fn puts (str) ...
fn exit (int) ...
fn malloc (int --- ptr) ...
fn fprintf (int any str) ...
fn printf (any str) ...
fn puts (str) ...
}

0 comments on commit 65c316e

Please sign in to comment.