dscx language design concept
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
include maths::sqrt
|
||||
|
||||
trait AsUnit {
|
||||
fn unit(self) -> Self;
|
||||
}
|
||||
|
||||
class Point2 {
|
||||
let x: isize,
|
||||
let y: isize,
|
||||
|
||||
fn len(self) -> isize {
|
||||
sqrt(self.x * self.x + self.y * self.y)
|
||||
}
|
||||
}
|
||||
|
||||
// can inherit from a single class + many traits
|
||||
class Point3: Point2 + AsUnit {
|
||||
let z: isize,`
|
||||
|
||||
fn len(self) -> isize {
|
||||
// implicit return of internal expressions
|
||||
sqrt(self.x * self.x + self.y * self.y + self.z * self.z)
|
||||
}
|
||||
|
||||
fn AsUnit.unit(self) -> Self {
|
||||
let len = self.len();
|
||||
Self {
|
||||
x: self.x / len,
|
||||
y: self.y / len,
|
||||
z: self.y / len,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn do_matches(val: AsUnit) -> bool {
|
||||
|
||||
// can use kotlin-style "is" syntax to find sub-classes and implementors.
|
||||
if match val {
|
||||
is Point3 => true, // only Point3 as it has no subclasses.
|
||||
// this also implicitly downcasts us to a Point3 so we can use methods specific to this class!
|
||||
is Point2 => true, // returns true for Point2 and Point3 as it is a subclass
|
||||
is AsUnit => true, // always true.
|
||||
} { return true; }
|
||||
|
||||
unreachable() // this should probably crash the program
|
||||
|
||||
// we can match against any boolean expression. this lazily evaluates each arm one by one.
|
||||
match {
|
||||
do_some_processing() == 1 => println("success!") { style => style.colour = Colour::Red }
|
||||
something_else() == 1 => println!("success") // we can omit the trailing lambda when it's
|
||||
|
||||
// alternative syntax for the same thing as above!
|
||||
val is Point3 => { return true; }
|
||||
val is AsUnit => { return true; }
|
||||
false == true => { return false; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
// of course normal rust matches also apply
|
||||
}
|
||||
|
||||
|
||||
/* uilib.dscx */
|
||||
|
||||
class UiBuilder {
|
||||
...
|
||||
fn text_entry() -> Interaction
|
||||
}
|
||||
|
||||
class Interaction {
|
||||
fn clicked() -> bool;
|
||||
}
|
||||
|
||||
/* app.dscx */
|
||||
|
||||
pub enum Action {
|
||||
SubmitForm(PasswordForm)
|
||||
}
|
||||
|
||||
class PasswordForm {
|
||||
let username: String,
|
||||
let password: String,
|
||||
}
|
||||
|
||||
|
||||
class UserInterface {
|
||||
const MESSAGE: str = "Run Emulator";
|
||||
let form: PasswordForm;
|
||||
let state: EmulatorState;
|
||||
|
||||
fn new(state: EmulatorState) -> Self {
|
||||
Self {
|
||||
form: PasswordForm {
|
||||
username: String::new(),
|
||||
password: String::new()
|
||||
},
|
||||
state
|
||||
}
|
||||
}
|
||||
|
||||
fn ui(self, ui: UiBuilder) -> Action {
|
||||
|
||||
ui_lib::Form(self.form, ui, "login") { form, ui ->
|
||||
ui.text_entry(form.username) { view ->
|
||||
view.placeholder = "enter username";
|
||||
}
|
||||
|
||||
ui.text_entry(form.password); // also acceptable syntax. placeholder has a default value!
|
||||
|
||||
if ui.button("Submit").clicked() {
|
||||
return Action::SubmitForm(form);
|
||||
}
|
||||
}
|
||||
|
||||
ui.vertical {
|
||||
my_lib::StatusIndicator(self.state.status, ui);
|
||||
|
||||
if ui.button("Run Emulator").clicked() {
|
||||
self.state.run();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user