Skip to content

Commit

Permalink
Struct equality (actually more like "hash-consing") in stackmac.
Browse files Browse the repository at this point in the history
  • Loading branch information
cpressey committed Jun 30, 2021
1 parent 4a01947 commit 18898ef
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 15 deletions.
50 changes: 43 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -703,6 +703,13 @@ Equality, inequality, boolean operators.
| }
= struth

| fun main() {
| if "five" == "five" and (("six" != "seven") or false) {
| print("struth")
| }
| }
= struth

Equality cannot be checked between two values of different types.

| fun main() {
Expand Down Expand Up @@ -864,13 +871,42 @@ doesn't matter if this is structural equality or identity.)
| }
= True

/| struct person { age: integer; name: string }
/| main = fun() {
/| j = make person(age: 23, name:"Jake");
/| k = make person(age: 23, name:"John");
/| j == k
/| }
/= False
| struct person { age: integer; name: string }
| main = fun() {
| j = make person(age: 23, name:"Jake");
| k = make person(age: 23, name:"John");
| j == k
| }
= False

| struct person { age: integer; name: string }
| main = fun() {
| j = make person(age: 23, name:"Jake");
| k = make person(age: 21, name:"Jake");
| j != k
| }
= True

Structs of two different types cannot be tested for equality.

| struct person { age: integer; name: string }
| struct individual { age: integer; name: string }
| main = fun() {
| j = make person(age: 23, name:"Jake");
| k = make individual(age: 23, name:"Jake");
| j == k
| }
? mismatch

Structs cannot be compared for ordering.

| struct person { age: integer; name: string }
| main = fun() {
| j = make person(age: 23, name:"Jake");
| k = make person(age: 21, name:"Jake");
| j > k
| }
? structs cannot be compared for order

Structs can be passed to functions.

Expand Down
2 changes: 2 additions & 0 deletions src/castile/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ def type_of(self, ast):
type1 = self.type_of(ast.children[0])
type2 = self.type_of(ast.children[1])
self.assert_eq(type1, type2)
if ast.value in ('>', '>=', '<', '<=') and isinstance(type1, Struct):
raise CastileTypeError("structs cannot be compared for order")
ast.type = Boolean()
elif ast.tag == 'Not':
type1 = self.type_of(ast.children[0])
Expand Down
25 changes: 17 additions & 8 deletions src/castile/stackmac.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@ def boo(b):
return 0


def add_string(strings, s):
"""Adds a string to the pool, deduping it. Returns the index of the
entry of the string, whether new or existing."""
for n, t in enumerate(strings):
if t == s:
return n
strings.append(s)
return len(strings) - 1


def run(program, strings):
global labels
ip = 0
Expand Down Expand Up @@ -52,21 +62,21 @@ def run(program, strings):
elif name == 'concat':
b = strings[stack.pop()]
a = strings[stack.pop()]
strings.append(builtin(a, b))
stack.append(len(strings) - 1)
pos = add_string(strings, builtin(a, b))
stack.append(pos)
elif name == 'len':
a = strings[stack.pop()]
stack.append(builtin(a))
elif name == 'substr':
k = stack.pop()
p = stack.pop()
s = strings[stack.pop()]
strings.append(builtin(s, p, k))
stack.append(len(strings) - 1)
pos = add_string(strings, builtin(s, p, k))
stack.append(pos)
elif name == 'str':
n = stack.pop()
strings.append(builtin(n))
stack.append(len(strings) - 1)
pos = add_string(strings, builtin(n))
stack.append(pos)
else:
raise NotImplementedError(name)
elif op == 'rts':
Expand Down Expand Up @@ -235,8 +245,7 @@ def main(args):
else:
match = re.match(r"^'(.*?)'$", arg)
if match:
strings.append(match.group(1))
arg = len(strings) - 1
arg = add_string(strings, match.group(1))
else:
arg = int(arg)
p.append((op, arg))
Expand Down

0 comments on commit 18898ef

Please sign in to comment.