#!/usr/bin/env nomsu -V4.10.12.7 # A library for simple object oriented programming. test: an (Empty) is a thing a (Dog) is a thing: [%it, %its] = [Dog, Dog] (%its::set up) means: %its.barks or= 0 [%its::bark, %its::woof] all mean: %barks = [: for % in 1 to %its.barks: add "Bark!"] return (%barks::joined with " ") (%it::gets pissed off) means: %it.barks += 1 (Dog).genus = "Canus" %d = (a Dog with {barks: 2}) assume "\%d" == "Dog {barks: 2}" assume (type of %d) == "Dog" assume (%d is a "Dog") assume %d.barks == 2 assume ((%d::bark) == "Bark! Bark!") assume ((%d::woof) == "Bark! Bark!") %d::gets pissed off assume (%d.barks == 3) assume ((%d::bark) == "Bark! Bark! Bark!") assume (%d.genus == "Canus") assume ("\(%d.class)" == "Dog") assume (%d.genus == "Canus") assume (%d.barks == 3) %d2 = (a Dog) assume (%d2.barks == 0) or barf "Default initializer failed" with {%d: a Dog with {barks: 1}}: assume ((%d::bark) == "Bark!") a (Corgi) is a thing: [%it, %its] = [Corgi, Corgi] %it [set up, gets pissed off] like a (Dog) (%it::as text) means "Dogloaf \({: for %k = %v in %it: add %k = %v })" (%its::sploot) means "sploooot" [%its::bark, %its::woof] all mean: %barks = [: for % in 1 to %its.barks: add "Yip!"] return (%barks::joined with " ") %corg = (a Corgi) assume (%corg.barks == 0) assume "\%corg" == "Dogloaf {barks: 0}" with {%d: a Corgi with {barks: 1}}: assume ((%d::sploot) == "sploooot") or barf "subclass method failed" assume ((%d::bark) == "Yip!") or barf "inheritance failed" assume ((%d::woof) == "Yip!") with {%d: a Dog with {barks: 2}}: assume ((%d::bark) == "Bark! Bark!") a (Vec) is a thing with {x, y}: %its = (Vec) (%its::+ %other) means (Vec {x: %its.x + %other.x, y: %its.y + %other.y}) assume ((Vec {x: 1, y:2 }) + (Vec {x: 10, y: 10})) == (Vec {x: 11, y: 12}) assume (((Vec {x: 1, y:2 }) + (Vec {x: 10, y: 10})) != (Vec {x: 0, y: 0})) [..] %it can %actions like a %class, %it can %actions like an %class %it has %actions like a %class, %it has %actions like an %class %it %actions like a %class, %it %actions like an %class ..all compile to: %lua = (Lua "") %class_expr = (%class as lua expr) %lines = [] for %a in %actions: %lines::add "\(%it as lua expr).\(%a.stub::as lua id) = \%class_expr.\(%a.stub::as lua id)" %lua::add %lines joined with "\n" return %lua %METAMETHOD_MAP = {..} "as text": "__tostring", "clean up": "__gc", "+": "__add", "-": "__sub" "*": "__mul", "/": "__div", negative: "__unm", "//": "__idiv", mod: "__mod" "^": "__pow", "&": "__band", "|": "__bor", "~": "__bxor", "~": "__bnot" "<<": "__bshl", ">>": "__bshr", "==": "__eq", "<": "__lt", "<=": "__le" "set 1 =": "__newindex", size: "__len", iterate: "__ipairs", "iterate all": "__pairs" ((% as text like a dict)'s meaning) = ({}'s metatable).__tostring externally (..) a class named %classname with %members ((initialize %it)'s meaning) ..means: %class = {__type: %classname} %class.__index = %class %class.class = %class %class.__tostring = (% -> "\(%.__type) \(% as text like a dict)") %class.__eq = ({}'s metatable).__eq %class.__len = ({}'s metatable).__len if %members: %class.__members = %members %class.__newindex = (..) for (%its %key = %value): if %members.%key: rawset %its %key %value ..else: barf "Cannot set \%key, it's not one of the allowed member fields." set %class's metatable to {..} __tostring: (%class) -> %class.__type __call: for (%class with %initial_values): if (%initial_values == (nil)): return %class set %initial_values's metatable to %class if %initial_values.set_up: %initial_values::set up return %initial_values if ((initialize)'s meaning): initialize %class for %stub = %metamethod in %METAMETHOD_MAP: if %class.(%stub::as lua id): %class.%metamethod = %class.(%stub::as lua id) return %class [..] a %classname is a thing with %members %class_body an %classname is a thing with %members %class_body ..all compile to: %class_id = (%classname.stub::as lua id) if %class_body: %body_lua = (%class_body as lua) %body_lua::remove free vars [%class_id] %body_lua::declare locals return (..) Lua "\ ..\%class_id = a_class_named_1_with(\(quote %classname.stub), \(%members as lua)\(..) (Lua ", function(\%class_id)\n \%body_lua\nend") if %class_body else "" ..) a_\%class_id = function(initial_values) return \(%classname.stub::as lua id)(initial_values or {}) end an_\%class_id, a_\(%class_id)_with, an_\(%class_id)_with = \ ..a_\%class_id, a_\%class_id, a_\%class_id" [a %classname is a thing %class_body, an %classname is a thing] all parse as (..) a %classname is a thing with (nil) %class_body