deimos-lang/sketching/sketch.dm
2024-11-24 23:08:27 -06:00

175 lines
3.6 KiB
Plaintext

ns nonavosa_rail
pub mod train {
pub int Train {
name: String
primary_color: Color
destination: String
fn blow_horn(): IO
fn set_volume_by(factor: Number)
}
pub enum Color {
White, Blue, Red
}
pub fn int Printer {
(message: String): IO
}
pub fn create(props: Props<Train> & { printer: Printer }): Train = SimpleTrain { ...props } with { volume = 80.0 }
abs impl : Train {
#get #set
fld volume: Double
}
impl SimpleTrain : AbstractTrain {
printer: Printer
override fn set_volume(volume) {
if (volume < 0 || volume > 100) {
throw IllegalArgumentException {
message: `Volume $volume is outside of bounds 0-100.`,
argument: volume
}
}
this.volume = volume
}
impl fn blow_horn() = printer(`Train named $name is blowing it's horn at volume $volume!`)
-> { s => s.append('Hello from SimpleTrain!') }
impl fn set_volume_by(factor) = set_volume(volume * factor)
}
}
fn main(args) {
let train = train::create {
name: 'Test Train',
primary_color: train::Color::Blue,
destination: 'Nonavosa Central',
printer: { msg => println(msg) }
}
train.set_volume_by(1.1)
train.blow_horn()
let anonymous_train = train::Train {
name: 'Anonymous Train',
primary_color: train::Color::Red,
destination: 'Nonavosa North',
impl fn blow_horn() = println('Choo Choo!')
impl fn set_volume_by = throw MethodNotSupported
}
try {
anonymous_train.set_volume_by(3.0)
} catch (e: MethodNotSupported) {
println e.message
}
anonymous_train.blow_horn() -> { println('After blow horn, assuming nothing went wrong before') }
}
// some other file
fn log_printer(message) impl nonavosa_rail::train::Printer = msg =>
io::open_file('log.txt', io::Mode::Append)
-> { f => f.append(msg) }
-> io::close_file
fn main() {
nonavosa_rail::main(log_printer)
}
// io.dm
ns io
decl extern fn println(s: String)
#target[lua]
decl extern fn _open_file(filename: String, mode: String): LuaTable
#target[lua]
pub fn open_file(filename: String, mode: Mode): IO<File, LuaError> {
try {
let lua_file_handle = lua {% fs.open(${filename}, ${mode.as_lua_string()}) %}
Success(LuaFile { lua_file_handle })
} catch (e: LuaError) {
Failure(e)
}
}
#target[lua]
pub fn close_file(file): impl IO<File, LuaError> = file.close()
pub int File : Stream
#target[lua]
impl LuaFile : File {
#get
fld lua_file_handle
impl fn append(data) {
try {
lua {% ${lua_file_handle}.write(${data}) %}
Success(self)
} catch (e: LuaError) {
Failure(e)
}
}
impl fn close() {
try {
lua {% ${lua_file_handle}.close() %}
Success
} catch (e: LuaError) {
Failure(e)
}
}
}
pub enum Mode {
Append, Write, Read
}
pub enum IO<S: Stream = Stream, E?> : Chainable<IO<S, E>> {
Success(stream?: S) {
impl fn call() {
try {
do_call(stream)
} catch (e: E) {
Failure(e)
}
}
},
Failure(_) {
impl fn call() = self
};
fn <N: Stream> do_call(stream: S): IO<N, E>
}
pub int Stream {
fn append(data: String): IO<Self>
fn close(): IO
}
// chain.dm
pub fn int Chainable<N> {
(): N
}