diff options
author | Himbeer <himbeer@disroot.org> | 2024-08-30 19:29:38 +0200 |
---|---|---|
committer | Himbeer <himbeer@disroot.org> | 2024-08-30 19:29:38 +0200 |
commit | 358edcaaeadfe632ff9a3a0479b11785c9ca2466 (patch) | |
tree | 1005e1c959c1d1970df07de181c1a8db2653df70 | |
parent | 56ccd1992d5a0e420200b36e394f9ee39458e9eb (diff) |
Add redeclaration checks for functions and locals
Closes #1.
-rw-r--r-- | decl.go | 28 | ||||
-rw-r--r-- | generate.go | 26 |
2 files changed, 54 insertions, 0 deletions
@@ -0,0 +1,28 @@ +// SPDX-FileCopyrightText: 2024 Himbeer <himbeer@disroot.org> +// +// SPDX-License-Identifier: GPL-3.0-or-later + +package main + +var funcs = map[string]struct{}{} +var localConsts = map[string]map[string]string{} +var localMuts = map[string]map[string]struct{}{} + +func isDeclared(name string, toplevel bool) bool { + if toplevel { + return isDeclaredToplevel(name) + } + + return isDeclaredLocal(currentFunc, name) +} + +func isDeclaredToplevel(name string) bool { + _, ok := funcs[name] + return ok +} + +func isDeclaredLocal(function string, local string) bool { + _, constant := localConsts[function][local] + _, mutable := localMuts[function][local] + return constant || mutable +} diff --git a/generate.go b/generate.go index 3fa09f7..511ce05 100644 --- a/generate.go +++ b/generate.go @@ -11,6 +11,8 @@ import ( "strings" ) +var currentFunc string + var funcRegIndex int func allocReg() string { @@ -61,6 +63,7 @@ func generate(root *rootExpr, w io.Writer, errs chan<- error) { for _, toplevel := range root.toplevels { if err := generateToplevel(toplevel, w); err != nil { errs <- err + select {} } } @@ -77,8 +80,19 @@ func generateToplevel(toplevel expression, w io.Writer) error { } func generateFunction(function *functionExpr, w io.Writer) error { + if isDeclared(function.name, true) { + return errAlreadyDeclared{name: function.name, line: function.line()} + } + resetRegs() + currentFunc = function.name + defer func() { currentFunc = "" }() + + funcs[currentFunc] = struct{}{} + localConsts[currentFunc] = map[string]string{} + localMuts[currentFunc] = map[string]struct{}{} + if function.link != defaultLinkage { fmt.Fprintf(w, "%s ", function.link) } @@ -129,21 +143,33 @@ func generateReturnStmt(stmt *returnStmt, w io.Writer) error { } func generateConstStmt(stmt *constStmt, toplevel bool, w io.Writer) error { + if isDeclared(stmt.name, toplevel) { + return errAlreadyDeclared{name: stmt.name, line: stmt.line()} + } + value, err := stmt.initial.generate(w) if err != nil { return err } + localConsts[currentFunc][stmt.name] = value + fmt.Fprintf(w, "%%%s =w add %s, 0\n", stmt.name, value) return nil } func generateMutStmt(stmt *mutStmt, toplevel bool, w io.Writer) error { + if isDeclared(stmt.name, toplevel) { + return errAlreadyDeclared{name: stmt.name, line: stmt.line()} + } + value, err := stmt.initial.generate(w) if err != nil { return err } + localMuts[currentFunc][stmt.name] = struct{}{} + fmt.Fprintf(w, "%%%s =l alloc4 4\n", stmt.name) fmt.Fprintf(w, "storew %s, %%%s\n", value, stmt.name) return nil |