aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHimbeer <himbeer@disroot.org>2024-08-30 19:29:38 +0200
committerHimbeer <himbeer@disroot.org>2024-08-30 19:29:38 +0200
commit358edcaaeadfe632ff9a3a0479b11785c9ca2466 (patch)
tree1005e1c959c1d1970df07de181c1a8db2653df70
parent56ccd1992d5a0e420200b36e394f9ee39458e9eb (diff)
Add redeclaration checks for functions and locals
Closes #1.
-rw-r--r--decl.go28
-rw-r--r--generate.go26
2 files changed, 54 insertions, 0 deletions
diff --git a/decl.go b/decl.go
new file mode 100644
index 0000000..179acb2
--- /dev/null
+++ b/decl.go
@@ -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