1
0

Add function return type check; Clean up

This commit is contained in:
Jeff 2023-12-31 16:46:21 -05:00
parent 0bec02344e
commit d3a9fb3a0e
7 changed files with 926 additions and 39 deletions

824
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -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"

View File

@ -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)
}
} }
} }

View File

@ -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()),

View File

@ -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(output_text); ui.label(error.to_string());
}
}
}); });
}); });
} }
} }
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!(),
}
}

View File

@ -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>,
where }
D: Deserializer<'de>,
{ impl MapVisitor {
todo!() 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
M: MapAccess<'de>,
{
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())
} }
} }

View File

@ -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))
} }