128 lines
2.7 KiB
Plaintext
128 lines
2.7 KiB
Plaintext
ns nr::train
|
|
|
|
use object::{assign, Props, props!}
|
|
|
|
pub int Train
|
|
name: String
|
|
primaryColor: Color
|
|
|
|
fld destination: String
|
|
fld volume: Int
|
|
|
|
fn blowHorn() -> IO
|
|
end
|
|
|
|
pub enum Color
|
|
White,
|
|
Blue,
|
|
Red
|
|
end
|
|
|
|
pub type Printer = fn (message: String) -> IO
|
|
|
|
pub fn create(props: obj Props<Train> + { printer: Printer }) -> Train =
|
|
SimpleTrain(props).with {
|
|
volume = 80
|
|
}
|
|
|
|
class SimpleTrain : Train
|
|
props!::<Train>()
|
|
printer: Printer
|
|
|
|
ctor(props: obj Props<Train> + { printer: Printer })
|
|
assign(self, props)
|
|
end
|
|
|
|
impl fn blowHorn() -> IO
|
|
printer("Train ${name} is blowing its horn at volume ${volume}!")
|
|
end
|
|
end
|
|
|
|
pub fn createViaObj(props: obj Props<Train>, printer: Printer) -> obj Train
|
|
obj {
|
|
...props,
|
|
printer,
|
|
blowHorn: fn () -> IO
|
|
printer("Dynamic object Train ${train} is blowing its horn at volume ${self.volume}!")
|
|
end
|
|
}
|
|
end
|
|
|
|
// props lib file
|
|
ns std::core::object
|
|
|
|
pub fn assign(target: obj, source: obj)
|
|
for [key, value] source.props() do
|
|
target[key] = value
|
|
end
|
|
end
|
|
|
|
pub type Props<T> = obj {
|
|
[K in keyof T]: T[K]
|
|
}
|
|
|
|
pub macro fn <T> props!(_: TokenStream) -> TokenStream
|
|
let result = TokenStream()
|
|
for [key, type] in std::intrinsics::propsAndTypes::<T>() do
|
|
result << quote! {
|
|
#key: #type
|
|
}
|
|
end
|
|
result
|
|
end
|
|
|
|
// io lib file
|
|
ns std::core
|
|
|
|
pub enum IO<S : Stream = Stream, E = Error> : fn () -> IO<S, E>
|
|
Success(stream: S)
|
|
impl ()
|
|
try
|
|
doCall(stream)
|
|
catch (e: E)
|
|
Failure(e)
|
|
end
|
|
end
|
|
end,
|
|
Failure(_)
|
|
impl ()
|
|
self
|
|
end
|
|
end;
|
|
|
|
int
|
|
fn <Z : Stream = S> doCall(stream: S) -> IO<Z, E>
|
|
end
|
|
end
|
|
|
|
// main example file
|
|
ns nr::example
|
|
|
|
use nr::train::{create, createViaObj, Train, Color}
|
|
|
|
fn main()
|
|
let train = create(obj {
|
|
name: 'Test Train',
|
|
primaryColor: Color::Blue,
|
|
destination: 'Nonavosa Central',
|
|
printer: println
|
|
})
|
|
train.blowHorn()
|
|
train.volume = 100
|
|
train.blowHorn()
|
|
|
|
let objTrain: obj Train = createViaObj(obj {
|
|
name: 'Obj Train',
|
|
primaryColor: Color::Red,
|
|
destination: 'Durandana',
|
|
printer: println
|
|
})
|
|
// Since it's an obj, we can dynamically add properties and override methods, similar to JS
|
|
objTrain.secondaryColor = Color::White
|
|
let originalBlowHorn = objTrain.blowHorn
|
|
objTrain.blowHorn = fn ()
|
|
originalBlowHorn()
|
|
println "Hello again! The train's colors are ${self.primaryColor} and ${self.secondaryColor}!"
|
|
end
|
|
objTrain.blowHorn()
|
|
end |