Skip to content

Commit 525a879

Browse files
gokrclaude
andcommitted
Complete slots terminology renaming and add operator support
- Rename remaining ivarArray references to slots in Object.hrd and types.nim - Fix classDeriveParentsSlotsMethodsImpl to return the created class - Add codegen support for == and ~= comparison operators - Add integer division (//), backslash (\), and modulo (%) operators - Add percent symbol mangling for selector names Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent ad67ec7 commit 525a879

5 files changed

Lines changed: 49 additions & 27 deletions

File tree

lib/core/Object.hrd

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,14 @@ Object>>clone <primitive primitiveClone>
2929
# Class-side methods (using class>> syntax)
3030
#====================================================================
3131

32-
Object class>>derive: ivarArray methods: methodBlock [
33-
# Create a subclass with instance variables AND define methods in one expression.
32+
Object class>>derive: slotsArray methods: methodBlock [
33+
# Create a subclass with extra slots AND define methods in one expression.
3434
# Usage: Person := Object derive: #(name age) methods: [
3535
# self >> greet [ "Hello, I am " + name ]
3636
# self >> haveBirthday [ age := age + 1 ]
3737
# ]
3838
| newClass |
39-
newClass := self derive: ivarArray.
39+
newClass := self derive: slotsArray.
4040
newClass extend: methodBlock.
4141
^ newClass
4242
]

src/harding/codegen/module.nim

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,9 +204,18 @@ proc genModule*(ctx: var CompilerContext, nodes: seq[Node],
204204
output.add("# Comparison Operators\n")
205205
output.add("#####################\n\n")
206206

207-
for op in ["<", "<=", ">", ">=", "="]:
207+
for op in ["<", "<=", ">", ">=", "=", "==", "~="]:
208208
output.add(genComparisonMethod(op))
209209

210+
# Generate integer division and modulo operators
211+
output.add("\n")
212+
output.add("# Integer Division and Modulo\n")
213+
output.add("#############################\n\n")
214+
215+
output.add(genBinaryOpMethod("//"))
216+
output.add(genBinaryOpMethod("\\"))
217+
output.add(genBinaryOpMethod("%"))
218+
210219
# Generate main proc for top-level statements
211220
output.add(genMainProc(ctx, topLevel, moduleName))
212221

src/harding/compiler/symbols.nim

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,14 @@ proc mangleSelector*(selector: string): string =
4646
result = result.replace("+", "plus")
4747
result = result.replace("*", "star")
4848
result = result.replace("/", "slash")
49+
result = result.replace("\\", "backslash")
4950
result = result.replace("<", "lt")
5051
result = result.replace(">", "gt")
5152
result = result.replace("=", "eq")
5253
result = result.replace("~", "tilde")
5354
result = result.replace("@", "at")
5455
result = result.replace("|", "pipe")
56+
result = result.replace("%", "percent")
5557
# Add nt_ prefix
5658
result = "nt_" & result
5759

src/harding/core/types.nim

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -751,13 +751,13 @@ proc newClass*(superclasses: seq[Class] = @[], slotNames: seq[string] = @[], nam
751751

752752
# Check for method selector conflicts between superclasses (only for directly-defined methods)
753753
# Inherited methods should not cause conflicts
754-
# Note: use derive:superclasses:ivarArray:methods: to specify method overrides
754+
# Note: use derive:parents:slots:methods: to specify method overrides
755755
var seenInstanceMethods: seq[string] = @[]
756756
var seenClassMethods: seq[string] = @[]
757757
for parent in superclasses:
758758
for selector in parent.methods.keys: # Only check directly-defined instance methods
759759
if selector in seenInstanceMethods:
760-
raise newException(ValueError, "Method selector conflict: '" & selector & "' exists in multiple superclasses (use derive:superclasses:ivarArray:methods: to specify method overrides)")
760+
raise newException(ValueError, "Method selector conflict: '" & selector & "' exists in multiple superclasses (use derive:parents:slots:methods: to specify method overrides)")
761761
seenInstanceMethods.add(selector)
762762
for selector in parent.classMethods.keys: # Only check directly-defined class methods
763763
if selector in seenClassMethods:

src/harding/interpreter/objects.nim

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1051,63 +1051,74 @@ proc classDeriveParentsSlotsMethodsImpl*(self: Class, args: seq[NodeValue]): Nod
10511051
self.name & "+Derived"
10521052
else:
10531053
"Anonymous"
1054-
let newClass = newClass(superclasses =actualParents, slotNames = slotNames, name = className)
1054+
let theClass = newClass(superclasses =actualParents, slotNames = slotNames, name = className)
10551055

10561056
# Execute method block if provided (to define/override methods and resolve conflicts)
10571057
# For now, skip block execution - it requires an interpreter context
10581058
# This could be enhanced later to support true method definition in the block
10591059
discard
10601060

1061+
return NodeValue(kind: vkClass, classVal: theClass)
1062+
10611063
proc classDeriveParentsSlotsGettersSettersMethodsImpl*(self: Class, args: seq[NodeValue]): NodeValue =
10621064
## Create a new class with multiple parents, slots, selective getters/setters, and methods
1063-
## args[0]: parents array
1064-
## args[1]: slot names array (all slots)
1065-
## args[2]: getters array (slots to generate getters for)
1066-
## args[3]: setters array (slots to generate setters for)
1067-
## args[4]: methods dictionary (optional)
1068-
if args.len < 4:
1065+
## args[0]: slot names array (all slots)
1066+
## args[1]: parents array
1067+
## args[2]: slots array (extra slots)
1068+
## args[3]: getters array (slots to generate getters for)
1069+
## args[4]: setters array (slots to generate setters for)
1070+
## args[5]: methods dictionary (optional)
1071+
if args.len < 5:
10691072
return nilValue()
10701073

1071-
# Extract parents array
1072-
var parents: seq[Class] = @[]
1074+
# Extract slot names (from derive: parameter)
1075+
var slotNames: seq[string] = @[]
10731076
if args[0].kind == vkInstance and args[0].instVal.kind == ikArray:
10741077
for elem in args[0].instVal.elements:
1078+
if elem.kind == vkString or elem.kind == vkSymbol:
1079+
let name = if elem.kind == vkString: elem.strVal else: elem.symVal
1080+
if name.len > 0:
1081+
slotNames.add(name)
1082+
1083+
# Extract parents array
1084+
var parents: seq[Class] = @[]
1085+
if args[1].kind == vkInstance and args[1].instVal.kind == ikArray:
1086+
for elem in args[1].instVal.elements:
10751087
if elem.kind == vkClass:
10761088
parents.add(elem.classVal)
10771089

10781090
# If no parents provided, use self as the parent
10791091
if parents.len == 0:
10801092
parents.add(self)
10811093

1082-
# Extract all slot names
1083-
var slotNames: seq[string] = @[]
1084-
if args[1].kind == vkInstance and args[1].instVal.kind == ikArray:
1085-
for elem in args[1].instVal.elements:
1094+
# Extract additional slot names (from slots: parameter)
1095+
if args[2].kind == vkInstance and args[2].instVal.kind == ikArray:
1096+
for elem in args[2].instVal.elements:
10861097
if elem.kind == vkString or elem.kind == vkSymbol:
10871098
let name = if elem.kind == vkString: elem.strVal else: elem.symVal
1088-
if name.len > 0:
1099+
if name.len > 0 and name notin slotNames:
10891100
slotNames.add(name)
10901101

10911102
# Extract getter slot names
10921103
var getterSlotNames: seq[string] = @[]
1093-
if args[2].kind == vkInstance and args[2].instVal.kind == ikArray:
1094-
for elem in args[2].instVal.elements:
1104+
if args[3].kind == vkInstance and args[3].instVal.kind == ikArray:
1105+
for elem in args[3].instVal.elements:
10951106
if elem.kind == vkString or elem.kind == vkSymbol:
10961107
let name = if elem.kind == vkString: elem.strVal else: elem.symVal
10971108
if name.len > 0:
10981109
getterSlotNames.add(name)
10991110

11001111
# Extract setter slot names
11011112
var setterSlotNames: seq[string] = @[]
1102-
if args[3].kind == vkInstance and args[3].instVal.kind == ikArray:
1103-
for elem in args[3].instVal.elements:
1113+
if args[4].kind == vkInstance and args[4].instVal.kind == ikArray:
1114+
for elem in args[4].instVal.elements:
11041115
if elem.kind == vkString or elem.kind == vkSymbol:
11051116
let name = if elem.kind == vkString: elem.strVal else: elem.symVal
11061117
if name.len > 0:
11071118
setterSlotNames.add(name)
11081119

11091120
# Create the new class
1110-
let actualParents = if args[0].kind == vkNil: @[self] else: parents
1121+
let actualParents = if args[1].kind == vkNil: @[self] else: parents
11111122
let className = if parents.len > 0 and parents[0].name.len > 0:
11121123
parents[0].name & "+Derived"
11131124
elif self.name.len > 0:
@@ -1130,8 +1141,8 @@ proc classDeriveParentsSlotsGettersSettersMethodsImpl*(self: Class, args: seq[No
11301141
addMethodToClass(newClass, setterName, setter, isClassMethod = false)
11311142

11321143
# Extract and add methods from dictionary if provided
1133-
if args.len >= 5 and args[4].kind == vkInstance and args[4].instVal.kind == ikTable:
1134-
let methodTable = args[4].instVal
1144+
if args.len >= 6 and args[5].kind == vkInstance and args[5].instVal.kind == ikTable:
1145+
let methodTable = args[5].instVal
11351146
for key, value in methodTable.entries.pairs:
11361147
if key.kind == vkSymbol and value.kind == vkBlock:
11371148
let selector = key.symVal

0 commit comments

Comments
 (0)