Add function return type check; Clean up
This commit is contained in:
parent
0bec02344e
commit
d3a9fb3a0e
824
Cargo.lock
generated
824
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
15
Cargo.toml
15
Cargo.toml
@ -17,8 +17,16 @@ opt-level = 1
|
|||||||
opt-level = 3
|
opt-level = 3
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
ansi_term = "0.12.1"
|
||||||
clap = { version = "4.4.4", features = ["derive"] }
|
clap = { version = "4.4.4", features = ["derive"] }
|
||||||
csv = "1.2.2"
|
csv = "1.2.2"
|
||||||
|
egui = "0.24.1"
|
||||||
|
eframe = { version = "0.24.1", default-features = false, features = [
|
||||||
|
"accesskit",
|
||||||
|
"default_fonts",
|
||||||
|
"glow",
|
||||||
|
"persistence",
|
||||||
|
] }
|
||||||
libc = "0.2.148"
|
libc = "0.2.148"
|
||||||
log = "0.4.20"
|
log = "0.4.20"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
@ -29,13 +37,6 @@ serde = { version = "1.0.188", features = ["derive"] }
|
|||||||
serde_json = "1.0.107"
|
serde_json = "1.0.107"
|
||||||
toml = "0.8.1"
|
toml = "0.8.1"
|
||||||
tree-sitter = "0.20.10"
|
tree-sitter = "0.20.10"
|
||||||
egui = "0.24.1"
|
|
||||||
eframe = { version = "0.24.1", default-features = false, features = [
|
|
||||||
"default_fonts", # Embed the default egui fonts.
|
|
||||||
"glow", # Use the glow rendering backend. Alternative: "wgpu".
|
|
||||||
"persistence", # Enable restoring app state when restarting the app.
|
|
||||||
] }
|
|
||||||
ansi_term = "0.12.1"
|
|
||||||
|
|
||||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||||
env_logger = "0.10"
|
env_logger = "0.10"
|
||||||
|
@ -100,6 +100,10 @@ impl AbstractTree for Block {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn expected_type(&self, context: &Map) -> Result<Type> {
|
fn expected_type(&self, context: &Map) -> Result<Type> {
|
||||||
self.statements.last().unwrap().expected_type(context)
|
if let Some(statement) = self.statements.last() {
|
||||||
|
statement.expected_type(context)
|
||||||
|
} else {
|
||||||
|
Ok(Type::None)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,6 +69,8 @@ impl AbstractTree for ValueNode {
|
|||||||
let body_node = child.child(child_count - 1).unwrap();
|
let body_node = child.child(child_count - 1).unwrap();
|
||||||
let body = Block::from_syntax_node(source, body_node, &function_context)?;
|
let body = Block::from_syntax_node(source, body_node, &function_context)?;
|
||||||
|
|
||||||
|
return_type.inner().check(&body.expected_type(context)?)?;
|
||||||
|
|
||||||
let r#type = Type::Function {
|
let r#type = Type::Function {
|
||||||
parameter_types,
|
parameter_types,
|
||||||
return_type: Box::new(return_type.take_inner()),
|
return_type: Box::new(return_type.take_inner()),
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::{fs::read_to_string, path::PathBuf};
|
use std::{fs::read_to_string, path::PathBuf};
|
||||||
|
|
||||||
use dust_lang::{Interpreter, Map, Result, Value};
|
use dust_lang::{Interpreter, Map, Result, Value};
|
||||||
use egui::{Align, Layout};
|
use egui::{Align, Color32, Layout, RichText};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
@ -36,6 +36,8 @@ impl App {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cc.egui_ctx.set_zoom_factor(1.2);
|
||||||
|
|
||||||
if path.is_file() {
|
if path.is_file() {
|
||||||
create_app(path)
|
create_app(path)
|
||||||
} else {
|
} else {
|
||||||
@ -62,6 +64,7 @@ impl eframe::App for App {
|
|||||||
if ui.button("Quit").clicked() {
|
if ui.button("Quit").clicked() {
|
||||||
ctx.send_viewport_cmd(egui::ViewportCommand::Close);
|
ctx.send_viewport_cmd(egui::ViewportCommand::Close);
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.add_space(16.0);
|
ui.add_space(16.0);
|
||||||
|
|
||||||
egui::widgets::global_dark_light_mode_buttons(ui);
|
egui::widgets::global_dark_light_mode_buttons(ui);
|
||||||
@ -90,13 +93,44 @@ impl eframe::App for App {
|
|||||||
ui.code_editor(&mut self.source);
|
ui.code_editor(&mut self.source);
|
||||||
});
|
});
|
||||||
|
|
||||||
let output_text = match &self.output {
|
match &self.output {
|
||||||
Ok(value) => value.to_string(),
|
Ok(value) => {
|
||||||
Err(error) => error.to_string(),
|
display_value(value, ui);
|
||||||
};
|
}
|
||||||
|
Err(error) => {
|
||||||
|
ui.label(error.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ui.label(output_text);
|
fn display_value(value: &Value, ui: &mut egui::Ui) {
|
||||||
});
|
match value {
|
||||||
|
Value::List(list) => {
|
||||||
|
ui.collapsing("list", |ui| {
|
||||||
|
for value in list.items().iter() {
|
||||||
|
display_value(value, ui);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Value::Map(_) => todo!(),
|
||||||
|
Value::Function(function) => {
|
||||||
|
ui.label(function.to_string());
|
||||||
|
}
|
||||||
|
Value::String(string) => {
|
||||||
|
ui.label(RichText::new(string).color(Color32::GREEN));
|
||||||
|
}
|
||||||
|
Value::Float(float) => {
|
||||||
|
ui.label(float.to_string());
|
||||||
|
}
|
||||||
|
Value::Integer(integer) => {
|
||||||
|
ui.label(RichText::new(integer.to_string()).color(Color32::BLUE));
|
||||||
|
}
|
||||||
|
Value::Boolean(boolean) => {
|
||||||
|
ui.label(RichText::new(boolean.to_string()).color(Color32::RED));
|
||||||
|
}
|
||||||
|
Value::Option(_) => todo!(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,13 @@
|
|||||||
use serde::{ser::SerializeMap, Deserialize, Deserializer, Serialize};
|
use serde::{
|
||||||
|
de::{MapAccess, Visitor},
|
||||||
|
ser::SerializeMap,
|
||||||
|
Deserialize, Serialize,
|
||||||
|
};
|
||||||
use std::{
|
use std::{
|
||||||
cmp::Ordering,
|
cmp::Ordering,
|
||||||
collections::BTreeMap,
|
collections::BTreeMap,
|
||||||
fmt::{self, Display, Formatter},
|
fmt::{self, Display, Formatter},
|
||||||
|
marker::PhantomData,
|
||||||
sync::{Arc, RwLock, RwLockReadGuard},
|
sync::{Arc, RwLock, RwLockReadGuard},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -132,11 +137,46 @@ impl Serialize for Map {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de> Deserialize<'de> for Map {
|
struct MapVisitor {
|
||||||
fn deserialize<D>(_deserializer: D) -> std::result::Result<Self, D::Error>
|
marker: PhantomData<fn() -> Map>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MapVisitor {
|
||||||
|
fn new() -> Self {
|
||||||
|
MapVisitor {
|
||||||
|
marker: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> Visitor<'de> for MapVisitor {
|
||||||
|
type Value = Map;
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
|
||||||
|
formatter.write_str("Any valid whale data.")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_map<M>(self, mut access: M) -> std::result::Result<Map, M::Error>
|
||||||
where
|
where
|
||||||
D: Deserializer<'de>,
|
M: MapAccess<'de>,
|
||||||
{
|
{
|
||||||
todo!()
|
let map = Map::new();
|
||||||
|
|
||||||
|
{
|
||||||
|
while let Some((key, value)) = access.next_entry::<String, Value>()? {
|
||||||
|
map.set(key, value, None).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(map)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> Deserialize<'de> for Map {
|
||||||
|
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: serde::Deserializer<'de>,
|
||||||
|
{
|
||||||
|
deserializer.deserialize_any(MapVisitor::new())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -614,7 +614,7 @@ impl<'de> Visitor<'de> for ValueVisitor {
|
|||||||
type Value = Value;
|
type Value = Value;
|
||||||
|
|
||||||
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
|
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
|
||||||
formatter.write_str("Any valid whale data.")
|
formatter.write_str("Dust-compatible data format.")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_bool<E>(self, v: bool) -> std::result::Result<Self::Value, E>
|
fn visit_bool<E>(self, v: bool) -> std::result::Result<Self::Value, E>
|
||||||
@ -776,11 +776,9 @@ impl<'de> Visitor<'de> for ValueVisitor {
|
|||||||
where
|
where
|
||||||
D: serde::Deserializer<'de>,
|
D: serde::Deserializer<'de>,
|
||||||
{
|
{
|
||||||
let _ = deserializer;
|
Ok(Value::Option(Some(Box::new(Value::deserialize(
|
||||||
Err(serde::de::Error::invalid_type(
|
deserializer,
|
||||||
serde::de::Unexpected::Option,
|
)?))))
|
||||||
&self,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_unit<E>(self) -> std::result::Result<Self::Value, E>
|
fn visit_unit<E>(self) -> std::result::Result<Self::Value, E>
|
||||||
@ -820,11 +818,9 @@ impl<'de> Visitor<'de> for ValueVisitor {
|
|||||||
{
|
{
|
||||||
let map = Map::new();
|
let map = Map::new();
|
||||||
|
|
||||||
{
|
|
||||||
while let Some((key, value)) = access.next_entry::<String, Value>()? {
|
while let Some((key, value)) = access.next_entry::<String, Value>()? {
|
||||||
map.set(key, value, None).unwrap();
|
map.set(key, value, None).unwrap();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Value::Map(map))
|
Ok(Value::Map(map))
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user