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
|
||||
|
||||
[dependencies]
|
||||
ansi_term = "0.12.1"
|
||||
clap = { version = "4.4.4", features = ["derive"] }
|
||||
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"
|
||||
log = "0.4.20"
|
||||
rand = "0.8.5"
|
||||
@ -29,13 +37,6 @@ serde = { version = "1.0.188", features = ["derive"] }
|
||||
serde_json = "1.0.107"
|
||||
toml = "0.8.1"
|
||||
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]
|
||||
env_logger = "0.10"
|
||||
|
@ -100,6 +100,10 @@ impl AbstractTree for Block {
|
||||
}
|
||||
|
||||
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 = Block::from_syntax_node(source, body_node, &function_context)?;
|
||||
|
||||
return_type.inner().check(&body.expected_type(context)?)?;
|
||||
|
||||
let r#type = Type::Function {
|
||||
parameter_types,
|
||||
return_type: Box::new(return_type.take_inner()),
|
||||
|
@ -1,7 +1,7 @@
|
||||
use std::{fs::read_to_string, path::PathBuf};
|
||||
|
||||
use dust_lang::{Interpreter, Map, Result, Value};
|
||||
use egui::{Align, Layout};
|
||||
use egui::{Align, Color32, Layout, RichText};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
@ -36,6 +36,8 @@ impl App {
|
||||
}
|
||||
}
|
||||
|
||||
cc.egui_ctx.set_zoom_factor(1.2);
|
||||
|
||||
if path.is_file() {
|
||||
create_app(path)
|
||||
} else {
|
||||
@ -62,6 +64,7 @@ impl eframe::App for App {
|
||||
if ui.button("Quit").clicked() {
|
||||
ctx.send_viewport_cmd(egui::ViewportCommand::Close);
|
||||
}
|
||||
|
||||
ui.add_space(16.0);
|
||||
|
||||
egui::widgets::global_dark_light_mode_buttons(ui);
|
||||
@ -90,13 +93,44 @@ impl eframe::App for App {
|
||||
ui.code_editor(&mut self.source);
|
||||
});
|
||||
|
||||
let output_text = match &self.output {
|
||||
Ok(value) => value.to_string(),
|
||||
Err(error) => error.to_string(),
|
||||
};
|
||||
|
||||
ui.label(output_text);
|
||||
match &self.output {
|
||||
Ok(value) => {
|
||||
display_value(value, ui);
|
||||
}
|
||||
Err(error) => {
|
||||
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!(),
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,13 @@
|
||||
use serde::{ser::SerializeMap, Deserialize, Deserializer, Serialize};
|
||||
use serde::{
|
||||
de::{MapAccess, Visitor},
|
||||
ser::SerializeMap,
|
||||
Deserialize, Serialize,
|
||||
};
|
||||
use std::{
|
||||
cmp::Ordering,
|
||||
collections::BTreeMap,
|
||||
fmt::{self, Display, Formatter},
|
||||
marker::PhantomData,
|
||||
sync::{Arc, RwLock, RwLockReadGuard},
|
||||
};
|
||||
|
||||
@ -132,11 +137,46 @@ impl Serialize for Map {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for Map {
|
||||
fn deserialize<D>(_deserializer: D) -> std::result::Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
todo!()
|
||||
struct MapVisitor {
|
||||
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
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
@ -614,7 +614,7 @@ impl<'de> Visitor<'de> for ValueVisitor {
|
||||
type Value = Value;
|
||||
|
||||
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>
|
||||
@ -776,11 +776,9 @@ impl<'de> Visitor<'de> for ValueVisitor {
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
let _ = deserializer;
|
||||
Err(serde::de::Error::invalid_type(
|
||||
serde::de::Unexpected::Option,
|
||||
&self,
|
||||
))
|
||||
Ok(Value::Option(Some(Box::new(Value::deserialize(
|
||||
deserializer,
|
||||
)?))))
|
||||
}
|
||||
|
||||
fn visit_unit<E>(self) -> std::result::Result<Self::Value, E>
|
||||
@ -820,10 +818,8 @@ impl<'de> Visitor<'de> for ValueVisitor {
|
||||
{
|
||||
let map = Map::new();
|
||||
|
||||
{
|
||||
while let Some((key, value)) = access.next_entry::<String, Value>()? {
|
||||
map.set(key, value, None).unwrap();
|
||||
}
|
||||
while let Some((key, value)) = access.next_entry::<String, Value>()? {
|
||||
map.set(key, value, None).unwrap();
|
||||
}
|
||||
|
||||
Ok(Value::Map(map))
|
||||
|
Loading…
Reference in New Issue
Block a user