99 lines
3.5 KiB
Plaintext
99 lines
3.5 KiB
Plaintext
#!/usr/bin/env nomsu -V2.5.5.5
|
|
#
|
|
This file contains the implementation of an Object-Oriented programming system.
|
|
|
|
test:
|
|
object "Dog":
|
|
(class Dog).genus = "Canus"
|
|
method [initialize %] (%.barks or= 0)
|
|
method [bark, woof]:
|
|
%barks = ("Bark!" for % in 1 to (me).barks)
|
|
return (%barks joined with " ")
|
|
|
|
method [get pissed off] ((me).barks += 1)
|
|
|
|
%d = (new Dog {barks:2})
|
|
as %d:
|
|
assume ((me) == %d)
|
|
assume ((me).barks == 2)
|
|
assume ((bark) == "Bark! Bark!")
|
|
assume ((woof) == "Bark! Bark!")
|
|
get pissed off
|
|
assume ((me).barks == 3)
|
|
assume ((bark) == "Bark! Bark! Bark!")
|
|
assume ((me).genus == "Canus")
|
|
|
|
assume ("\(%d.class)" == "Dog")
|
|
assume (%d.genus == "Canus")
|
|
assume (%d.barks == 3)
|
|
as (new Dog) (assume ((me).barks == 0) or barf "Default initializer failed")
|
|
as (new Dog {barks:1}) (assume ((bark) == "Bark!"))
|
|
action [foo] (as (new Dog {barks:23}) (return (me).barks))
|
|
assume ((foo) == 23) or barf "Oops, \(foo) != 23"
|
|
as (new Dog {barks:101}):
|
|
try (as (new Dog {barks:8}) (barf)) and if it succeeds (barf)
|
|
assume ((me).barks == 101) or barf ".."
|
|
Error in nested 'as % %' failed to properly reset 'self'
|
|
|
|
object "Corgi" extends (class Dog) (method [sploot] "splooted")
|
|
%corg = (new Corgi)
|
|
assume (%corg.barks == 0)
|
|
as (new Corgi {barks:1}):
|
|
assume ((sploot) == "splooted") or barf "subclass method failed"
|
|
assume ((bark) == "Bark!") or barf "inheritance failed"
|
|
assume ((woof) == "Bark!")
|
|
compile [@, me] to (Lua value "self")
|
|
compile [method %actions %body] to:
|
|
%lua = (compile as (local action %actions %body))
|
|
for % in %actions:
|
|
to %lua write "\nclass.\(% as lua id) = \(% as lua id)"
|
|
return (..)
|
|
Lua ".."
|
|
do -- Method: \(%actions.(1).stub)
|
|
\%lua
|
|
end
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
parse [as %instance %body] as (..)
|
|
result of:
|
|
%old_self = (me)
|
|
(me) = %instance
|
|
try %body and if it barfs %msg:
|
|
(me) = %old_self
|
|
barf %msg
|
|
..or if it succeeds: (me) = %old_self
|
|
|
|
compile [object %classname extends %parent %class_body] to (..)
|
|
Lua ".."
|
|
do
|
|
local class = {name=\(%classname as lua expr)}
|
|
setmetatable(class, {
|
|
__index=\(%parent as lua expr),
|
|
__tostring=function(cls) return cls.name end,
|
|
__call=function(cls, inst)
|
|
inst = setmetatable(inst or {}, cls)
|
|
if cls.A_initialize_1 then
|
|
cls.A_initialize_1(inst)
|
|
end
|
|
return inst
|
|
end,
|
|
})
|
|
_ENV["A"..string.as_lua_id("new "..class.name)] = class
|
|
_ENV["A"..string.as_lua_id("new "..class.name.." 1")] = class
|
|
_ENV["A"..string.as_lua_id("class "..class.name)] = function() return class end
|
|
class.__index = class
|
|
class.class = class
|
|
|
|
\(%class_body as lua statements)
|
|
|
|
class.__tostring = class["A"..string.as_lua_id("as text")] or function(inst)
|
|
return inst.name..getmetatable(dict{}).__tostring(inst)
|
|
end
|
|
end
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
parse [object %classname %class_body] as (..)
|
|
object %classname extends (nil) %class_body
|