diff --git a/Cargo.lock b/Cargo.lock index 82b70f791..f52c63ee6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1083,7 +1083,7 @@ dependencies = [ "pretty_assertions", "rstest", "salsa", - "semver 1.0.17", + "semver 1.0.23", "smallvec", "smol_str", "strum 0.23.0", @@ -1138,7 +1138,7 @@ dependencies = [ "camino", "fe-parser2", "salsa-2022", - "semver 1.0.17", + "semver 1.0.23", "smol_str", ] @@ -1226,11 +1226,17 @@ dependencies = [ "camino", "clap 4.3.12", "codespan-reporting", + "dirs", "fe-common2", "fe-hir", "fe-hir-analysis", "fe-macros", + "include_dir", "salsa-2022", + "semver 1.0.23", + "serde", + "toml 0.8.13", + "walkdir", ] [[package]] @@ -1360,7 +1366,7 @@ dependencies = [ "insta", "logos", "pretty_assertions", - "semver 1.0.17", + "semver 1.0.23", "serde", "smol_str", "unescape", @@ -2569,7 +2575,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" dependencies = [ "once_cell", - "toml_edit", + "toml_edit 0.19.15", ] [[package]] @@ -2987,7 +2993,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.17", + "semver 1.0.23", ] [[package]] @@ -3185,9 +3191,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.17" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "semver-parser" @@ -3249,9 +3255,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" +checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0" dependencies = [ "serde", ] @@ -3657,14 +3663,26 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit", + "toml_edit 0.19.15", +] + +[[package]] +name = "toml" +version = "0.8.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4e43f8cc456c9704c851ae29c67e17ef65d2c30017c17a9765b89c382dc8bba" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.22.13", ] [[package]] name = "toml_datetime" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" dependencies = [ "serde", ] @@ -3679,7 +3697,20 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "winnow", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.22.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c127785850e8c20836d49732ae6abfa47616e60bf9d9f57c43c250361a9db96c" +dependencies = [ + "indexmap 2.2.6", + "serde", + "serde_spanned", + "toml_datetime", + "winnow 0.6.9", ] [[package]] @@ -4216,6 +4247,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "winnow" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86c949fede1d13936a99f14fafd3e76fd642b556dd2ce96287fbe2e0151bfac6" +dependencies = [ + "memchr", +] + [[package]] name = "winreg" version = "0.50.0" diff --git a/crates/common2/src/input.rs b/crates/common2/src/input.rs index 4eb82cba6..303a116a0 100644 --- a/crates/common2/src/input.rs +++ b/crates/common2/src/input.rs @@ -10,7 +10,7 @@ use crate::InputDb; #[salsa::input(constructor = __new_impl)] pub struct InputIngot { /// An absolute path to the ingot root directory. - /// The all files in the ingot should be located under this directory. + /// All files in the ingot should be located under this directory. #[return_ref] pub path: Utf8PathBuf, @@ -23,6 +23,7 @@ pub struct InputIngot { /// A list of ingots which the current ingot depends on. #[return_ref] + #[set(__set_external_ingots_impl)] pub external_ingots: BTreeSet, /// A list of files which the current ingot contains. @@ -72,6 +73,10 @@ impl InputIngot { pub fn root_file(&self, db: &dyn InputDb) -> InputFile { self.__get_root_file_impl(db).unwrap() } + + pub fn set_external_ingots(self, db: &mut dyn InputDb, ingots: BTreeSet) { + self.__set_external_ingots_impl(db).to(ingots); + } } #[salsa::input] diff --git a/crates/driver2/Cargo.toml b/crates/driver2/Cargo.toml index 8a8b6804e..f2789c179 100644 --- a/crates/driver2/Cargo.toml +++ b/crates/driver2/Cargo.toml @@ -19,3 +19,9 @@ macros = { path = "../macros", package = "fe-macros" } hir-analysis = { path = "../hir-analysis", package = "fe-hir-analysis" } camino = "1.1.4" clap = { version = "4.3", features = ["derive"] } +toml = "0.8.13" +serde = { version = "1", features = ["derive"] } +semver = "1.0.23" +walkdir = "2" +include_dir = "0.7" +dirs = "5.0.1" \ No newline at end of file diff --git a/crates/driver2/src/check.rs b/crates/driver2/src/check.rs new file mode 100644 index 000000000..92c493d1b --- /dev/null +++ b/crates/driver2/src/check.rs @@ -0,0 +1,142 @@ +use crate::{load_ingot, CheckArgs}; +use common::input::IngotDependency; +use common::{input::IngotKind, InputIngot}; +use fe_driver2::DriverDataBase; +use include_dir::{include_dir, Dir}; +use semver::Version; +use std::fs; +use std::path::PathBuf; +use std::{collections::BTreeSet, path::Path}; + +const STD_DIR: Dir = include_dir!("$CARGO_MANIFEST_DIR/../../library/std"); + +fn write_std_files(std_path: &Path) { + write_files_recursive(&STD_DIR, std_path); +} + +fn write_files_recursive(dir: &Dir<'_>, base_path: &Path) { + for file in dir.files() { + let file_path = base_path.join(file.path()); + if let Some(parent_dir) = file_path.parent() { + std::fs::create_dir_all(parent_dir).unwrap(); + } + std::fs::write(file_path, file.contents()).unwrap(); + } + + for subdir in dir.dirs() { + let subdir_path = base_path.join(subdir.path()); + std::fs::create_dir_all(&subdir_path).unwrap(); + write_files_recursive(subdir, &base_path); + } +} + +pub fn run_check(args: &CheckArgs) { + let std_path = match &args.std_path { + Some(path) => PathBuf::from(path.to_owned()), + None => { + let home_dir = dirs::home_dir().expect("Failed to get user home directory"); + home_dir.join(".fe/std") + } + }; + if !std_path.exists() { + println!("The standard library is not installed. Do you want to perform the write? (y/n)"); + let mut input = String::new(); + std::io::stdin().read_line(&mut input).unwrap(); + let input = input.trim().to_lowercase(); + if input == "y" || input == "yes" { + write_std_files(&std_path); + } else { + eprintln!( + "Cannot perform the write without the standard library being installed on disk" + ); + std::process::exit(2); + } + } + + let path = Path::new(&args.path); + if !path.exists() { + eprintln!("Path '{}' does not exist", path.display()); + std::process::exit(2); + } + + let mut db = DriverDataBase::default(); + + let std_ingot = load_ingot(&std_path, &mut db, IngotKind::Std, &mut BTreeSet::new()); + + if path.is_file() { + let source = fs::read_to_string(path).unwrap(); + check_single_file(path, source, std_ingot, &mut db, args.dump_scope_graph); + } else if path.is_dir() { + check_ingot(path, std_ingot, &mut db, args.dump_scope_graph); + } else { + eprintln!( + "Path '{}' is neither a file nor a directory", + path.display() + ); + std::process::exit(2); + } +} + +pub fn check_single_file( + path: &Path, + source: String, + std_ingot: InputIngot, + db: &mut DriverDataBase, + dump_scope_graph: bool, +) { + let mut dependencies = BTreeSet::from([IngotDependency::new("std", std_ingot)]); + let ingot = InputIngot::new( + db, + path.parent().unwrap().to_str().unwrap(), + IngotKind::StandAlone, + Version::new(0, 1, 0), + dependencies.clone(), + ); + + // let input_file = InputFile::new( + // db, + // ingot.clone(), + // path.file_name().unwrap().to_str().unwrap().into(), + // source, + // ); + // ingot.set_files(db, BTreeSet::from([input_file.clone()])); + // ingot.set_root_file(db, input_file); + + let top_mod = db.top_mod_from_file(path, &source); + db.run_on_top_mod(top_mod); + db.emit_diags(); + + // if dump_scope_graph { + // println!("{}", dump_scope_graph(db, top_mod)); + // } +} + +pub fn check_ingot( + path: &Path, + std_ingot: InputIngot, + db: &mut DriverDataBase, + dump_scope_graph: bool, +) { + let mut dependencies = BTreeSet::from([IngotDependency::new("std", std_ingot)]); + let mut main_ingot = load_ingot(path, db, IngotKind::Local, &mut dependencies); + + main_ingot.set_external_ingots(db, dependencies); + + db.run_on_ingot(std_ingot); + + let diags = db.format_diags(); + if !diags.is_empty() { + panic!("{diags}") + } + + db.run_on_ingot(main_ingot); + + let diags = db.format_diags(); + if !diags.is_empty() { + panic!("{diags}") + } + + // if dump_scope_graph { + // println!("{}", dump_scope_graph(db, top_mod)); + // } +} diff --git a/crates/driver2/src/lib.rs b/crates/driver2/src/lib.rs index 054114686..c574427cf 100644 --- a/crates/driver2/src/lib.rs +++ b/crates/driver2/src/lib.rs @@ -12,8 +12,11 @@ use common::{ InputDb, InputFile, InputIngot, }; use hir::{ - analysis_pass::AnalysisPassManager, diagnostics::DiagnosticVoucher, hir_def::TopLevelMod, - lower::map_file_to_mod, HirDb, LowerHirDb, ParsingPass, SpannedHirDb, + analysis_pass::AnalysisPassManager, + diagnostics::DiagnosticVoucher, + hir_def::TopLevelMod, + lower::{map_file_to_mod, module_tree}, + HirDb, LowerHirDb, ParsingPass, SpannedHirDb, }; use hir_analysis::{ name_resolution::{DefConflictAnalysisPass, ImportAnalysisPass, PathAnalysisPass}, @@ -58,6 +61,10 @@ impl DriverDataBase { self.run_on_file_with_pass_manager(top_mod, initialize_analysis_pass); } + pub fn run_on_ingot(&mut self, ingot: InputIngot) { + self.run_on_ingot_with_pass_manager(ingot, initialize_analysis_pass); + } + pub fn run_on_file_with_pass_manager(&mut self, top_mod: TopLevelMod, pm_builder: F) where F: FnOnce(&DriverDataBase) -> AnalysisPassManager<'_>, @@ -69,6 +76,18 @@ impl DriverDataBase { }; } + pub fn run_on_ingot_with_pass_manager(&mut self, ingot: InputIngot, pm_builder: F) + where + F: FnOnce(&DriverDataBase) -> AnalysisPassManager<'_>, + { + self.diags.clear(); + let tree = module_tree(self, ingot); + self.diags = { + let mut pass_manager = pm_builder(self); + pass_manager.run_on_module_tree(tree) + }; + } + pub fn top_mod_from_file(&mut self, file_path: &path::Path, source: &str) -> TopLevelMod { let kind = IngotKind::StandAlone; diff --git a/crates/driver2/src/main.rs b/crates/driver2/src/main.rs index 0533efd52..fade61bf8 100644 --- a/crates/driver2/src/main.rs +++ b/crates/driver2/src/main.rs @@ -1,41 +1,122 @@ -use fe_driver2::DriverDataBase; - -use clap::Parser; -use hir::hir_def::TopLevelMod; +use clap::{Args, Parser, Subcommand}; +use common::input::{IngotDependency, InputFile}; +use common::{input::IngotKind, InputDb, InputIngot}; +use semver::Version; +use serde::Deserialize; +use std::{collections::BTreeSet, path::Path}; +use walkdir::WalkDir; +mod check; #[derive(Parser, Debug)] #[command(author, version, about, long_about = None)] -struct Args { - /// The file to compile. +struct Cli { + #[command(subcommand)] + command: Commands, +} + +#[derive(Subcommand, Debug)] +enum Commands { + Check(CheckArgs), +} + +#[derive(Args, Debug)] +struct CheckArgs { + /// The path to check, either a single file or a directory. #[arg()] - file_path: String, + path: String, + + /// The std lib path. + #[arg(short, long)] + std_path: Option, /// Dump a graphviz dot file of the scope graph for the given file. #[arg(long = "dump-scope-graph", default_value_t = false)] dump_scope_graph: bool, } +#[derive(Deserialize, Debug)] +struct Manifest { + package: Package, + dependencies: Option>, +} + +#[derive(Deserialize, Debug)] +struct Package { + name: String, + version: String, +} + pub fn main() { - let args = Args::parse(); - let path = std::path::Path::new(&args.file_path); - if !path.exists() { - eprintln!("file '{}' does not exist", args.file_path); - std::process::exit(2); + let cli = Cli::parse(); + + match &cli.command { + Commands::Check(args) => check::run_check(args), } - let source = std::fs::read_to_string(&args.file_path).unwrap(); +} + +// fn dump_scope_graph(db: &DriverDataBase, top_mod: TopLevelMod) -> String { +// let mut s = vec![]; +// top_mod.scope_graph(db).write_as_dot(db, &mut s).unwrap(); +// String::from_utf8(s).unwrap() +// } + +fn load_ingot( + path: &Path, + db: &mut dyn InputDb, + ingot_kind: IngotKind, + dependencies: &mut BTreeSet, +) -> InputIngot { + let manifest_path = path.join("fe.toml"); + let manifest_content = + std::fs::read_to_string(&manifest_path).expect("Unable to read manifest file"); + let manifest: Manifest = toml::from_str(&manifest_content).expect("Invalid TOML format"); + + let project_name = &manifest.package.name; + let project_version = &manifest.package.version; - let mut db = DriverDataBase::default(); - let top_mod = db.top_mod_from_file(path, &source); - db.run_on_top_mod(top_mod); - db.emit_diags(); + let version = Version::parse(project_version).expect("Invalid version format"); - if args.dump_scope_graph { - println!("{}", dump_scope_graph(&db, top_mod)); + let ingot = InputIngot::new( + db, + path.to_str().unwrap(), + ingot_kind, + version, + BTreeSet::default(), + ); + + if let Some(deps) = &manifest.dependencies { + for dep in deps { + let dep_path = path.join(dep); + let dep_ingot = load_ingot(&dep_path, db, IngotKind::External, dependencies); + dependencies.insert(IngotDependency::new(dep, dep_ingot)); + } } + + let src_path = path.join("src"); + set_src_files(&src_path, db, ingot); + + ingot } -fn dump_scope_graph(db: &DriverDataBase, top_mod: TopLevelMod) -> String { - let mut s = vec![]; - top_mod.scope_graph(db).write_as_dot(db, &mut s).unwrap(); - String::from_utf8(s).unwrap() +fn set_src_files(path: &Path, db: &mut dyn InputDb, ingot: InputIngot) { + let input_files: BTreeSet<_> = WalkDir::new(path) + .into_iter() + // .expect("read_dir call failed") + .filter_map(|entry| entry.ok()) + .filter(|entry| entry.path().is_file()) + .map(|entry| { + let file_path = entry.path().to_str().unwrap().to_owned(); + let content = std::fs::read_to_string(&file_path).unwrap(); + InputFile::new(db, ingot, file_path.into(), content) + }) + .collect(); + + let root_file = input_files + .iter() + .find(|file| file.path(db).ends_with("lib.fe")) + .expect("Root file 'lib.fe' not found") + .clone(); + + ingot.set_root_file(db, root_file); + ingot.set_files(db, input_files); } diff --git a/crates/driver2/tests/std_lib.rs b/crates/driver2/tests/std_lib.rs new file mode 100644 index 000000000..3d5256bfc --- /dev/null +++ b/crates/driver2/tests/std_lib.rs @@ -0,0 +1,13 @@ +use fe_driver2::DriverDataBase; + +#[test] +fn check_std_lib() { + let mut driver = DriverDataBase::default(); + let std_ingot = library2::std_lib_input_ingot(&mut driver); + driver.run_on_ingot(std_ingot); + + let diags = driver.format_diags(); + if !diags.is_empty() { + panic!("{diags}") + } +} diff --git a/crates/hir/src/analysis_pass.rs b/crates/hir/src/analysis_pass.rs index ebfad04d0..eb21a2c09 100644 --- a/crates/hir/src/analysis_pass.rs +++ b/crates/hir/src/analysis_pass.rs @@ -1,4 +1,7 @@ -use crate::{diagnostics::DiagnosticVoucher, hir_def::TopLevelMod}; +use crate::{ + diagnostics::DiagnosticVoucher, + hir_def::{ModuleTree, TopLevelMod}, +}; /// All analysis passes that run analysis on the HIR top level module /// granularity should implement this trait. @@ -27,4 +30,14 @@ impl<'db> AnalysisPassManager<'db> { } diags } + + pub fn run_on_module_tree(&mut self, tree: &ModuleTree) -> Vec> { + let mut diags = vec![]; + for module in tree.all_modules() { + for pass in self.module_passes.iter_mut() { + diags.extend(pass.run_on_module(module)); + } + } + diags + } } diff --git a/library/core/fe.toml b/library/core/fe.toml new file mode 100644 index 000000000..71b5b7657 --- /dev/null +++ b/library/core/fe.toml @@ -0,0 +1,3 @@ +[package] +name = "core" +version = "1.0.0" \ No newline at end of file diff --git a/library/core/src/cmp.fe b/library/core/src/cmp.fe new file mode 100644 index 000000000..e69de29bb diff --git a/library/core/src/cmp/cmp.fe b/library/core/src/cmp/cmp.fe new file mode 100644 index 000000000..57bf955f4 --- /dev/null +++ b/library/core/src/cmp/cmp.fe @@ -0,0 +1,30 @@ +// /// Equal (e.g. `x == y`) +// pub trait Eq { +// fn eq(self, rhs: Rhs) -> Out +// } + +// /// Not equal (e.g. `x != y`) +// pub trait NotEq { +// fn not_eq(self, rhs: Rhs) -> Out +// } + +// /// Less than (e.g. `x < y`) +// pub trait Lt { +// fn lt(self, rhs: Rhs) -> Out +// } + +// /// Less than or equal (e.g. `x <= y`) +// pub trait LtEq { +// fn lt_eq(self, rhs: Rhs) -> Out +// } + +// /// Greater than (e.g. `x > y`) +// pub trait Gt { +// fn gt(self, rhs: Rhs) -> Out +// } + +// /// Greater than or equal (e.g. `x >= y`) +// pub trait GtEq { +// fn gt_eq(self, rhs: Rhs) -> Out +// } + diff --git a/library/core/src/ctrl.fe b/library/core/src/ctrl.fe new file mode 100644 index 000000000..e69de29bb diff --git a/library/core/src/ctrl/applicative.fe b/library/core/src/ctrl/applicative.fe new file mode 100644 index 000000000..dd828284c --- /dev/null +++ b/library/core/src/ctrl/applicative.fe @@ -0,0 +1,5 @@ +pub trait Applicative +where Self: * -> * +{ + fn pure(value: Value) -> Self +} \ No newline at end of file diff --git a/library/core/src/ctrl/applicative/option.fe b/library/core/src/ctrl/applicative/option.fe new file mode 100644 index 000000000..002d31de1 --- /dev/null +++ b/library/core/src/ctrl/applicative/option.fe @@ -0,0 +1,8 @@ +use ingot::data::{option::Option} +use ingot::ctrl::{applicative::Applicative, function::Fn} + +impl Applicative for Option { + fn pure(value: Value) -> Self { + Self::Some(value) + } +} diff --git a/library/core/src/ctrl/function.fe b/library/core/src/ctrl/function.fe new file mode 100644 index 000000000..42346e4c4 --- /dev/null +++ b/library/core/src/ctrl/function.fe @@ -0,0 +1,5 @@ +use ingot::data::tuple::Tuple + +pub trait Fn where Args: Tuple { + fn exec(self, args: Args) -> Ret +} diff --git a/library/core/src/ctrl/functor.fe b/library/core/src/ctrl/functor.fe new file mode 100644 index 000000000..ded9eb27f --- /dev/null +++ b/library/core/src/ctrl/functor.fe @@ -0,0 +1,9 @@ +use ingot::ctrl::{applicative::Applicative, function::Fn} +use ingot::data::tuple::Tuple + +pub trait Functor: Applicative +where Self: * -> * +{ + fn fmap(self: Self, morph: Morph) -> Self + where Morph: Fn<1, (Source), Target>, (Source): Tuple<1> +} diff --git a/library/core/src/ctrl/functor/option.fe b/library/core/src/ctrl/functor/option.fe new file mode 100644 index 000000000..bd65b693e --- /dev/null +++ b/library/core/src/ctrl/functor/option.fe @@ -0,0 +1,13 @@ +use ingot::ctrl::{functor::Functor, function::Fn} +use ingot::data::{option::Option, tuple::Tuple} + +impl Functor for Option { + fn fmap(self: Self, morph: Morph) -> Self + where Morph: Fn<1, (Source), Target>, (Source): Tuple<1> + { + match self { + Self::Some(self) => Self::pure(value: morph.exec(args: (self, ))) + Self::None => Self::None + } + } +} diff --git a/library/core/src/ctrl/monad copy.fe b/library/core/src/ctrl/monad copy.fe new file mode 100644 index 000000000..4f5e1e8e4 --- /dev/null +++ b/library/core/src/ctrl/monad copy.fe @@ -0,0 +1,173 @@ +// use self::option::Option + +// trait Applicative +// where Self: * -> * +// { +// fn pure(t: T) -> Self +// } + +// impl Applicative for Option { +// fn pure(t: T) -> Self { +// Option::Some(t) +// } +// } + +// trait Monad: Applicative +// where Self: * -> * +// { +// fn bind(self: Self) -> Self where F: Fn> +// } + +// impl Monad for Option { +// fn bind(self: Self) -> Self where F: Fn> { +// match self { +// Self::Some(self) => F::exec(t: self) +// Self::None => Self::None +// } +// } +// } + +// fn foo(f: F) +// where F: Fn(u8, u8, u8) -> u8 { +// where F: Fn<{u8, u8, u8}, u8> + +// } + +// fn f(u8, u8, u8) -> u8 {} // (u8, u8, u8) -> u8 +// fn g((u8, u8, u8)) -> u8 {} //((u8,u8,u8)) -> u8 + +// fn main() { +// f(1, 2, 3) // f.exec((1, 2, 3)) + +// let x = (1, 2, 3) +// f(x) +// g(x) + +// let args = {1, 2, 3} +// args.push(1) + +// let args = (1, 2, 3) +// f (1, 2, 3) +// f args + +// let x = ((u8, u8, u8)) +// let x = ((u8, u8, u8),) + +// f(args..) // f(x, y) f ( +// } +// (u8, u8, u8) -> u8 +// u8 -> u8 -> u8 -> u8 + + + +// impl Fn<((u8, u8, u8)), u8> for G + +// impl Fn<(u8, u8, u8), u8> for Foo { + +// } + +// trait Fn where T: FnArgs { +// fn exect(&self, t: T) -> U +// } + +// trait Fn +// where Arg: Tuple +// { +// fn call(self, arg : Arg) -> Ret +// } + +// trait FnMut where T: FnArgs { +// fn exect(&mut self, t: T) -> U +// } + +// trait Tuple; + +// fn map(t: T, f: F) -> U +// where F: Fn(T) -> U {...} + +// type MyFn = () + +// impl Fn for Foo { +// fn exec(&self, t: T) -> U { +// t.element(0) +// t.len() +// } +// } + +// impl Fn<(u8, u8>, Option> for MyFn { +// fn exec(t: (bool, bool)) -> Option { +// let (a, b) = t +// f(a, b) +// } +// } + +// #test +// fn my_test() { +// let f: MyFn = () +// let a = Option::Some(true).bind<_, _, _>(f) +// let a: Option = Option::Some(true).bind(f) +// } + + +// sub x y = x - y +// f = sub 1 // f 2 == 1 - 2 +// g = `sub` 1 // g 2 == 2 - 1 + + +// enum Result { +// Ok(T) +// Err(E) +// } +// impl Functor for Result<*, E> { // or Result<_, E> maybe? +// fn map>(self: Self, _ f: F) -> Self { +// match self { +// Result::Ok(a) => { +// return Result::Ok(f(a)) +// } +// Result::Err(e) => { +// return Result::Err(e) +// } +// } +// } +// } + + +// enum Res { // Result +// Err(E) +// Ok(T) +// } +// impl Functor for Res { +// fn map>(self: Self, _ f: F) -> Self { +// match self { +// Result::Ok(a) => { +// return Result::Ok(f(a)) +// } +// Result::Err(e) => { +// return Result::Err(e) +// } +// } +// } +// } + + + +// fn main() { +// let r = foo() +// r.map(|t| ...) +// } + + +// enum Result1 + +// Result<_, E> + +// Flip (Result) + + + +// ((+) `foldl` 0) [1..5] +// ((`foldl` 0) [1..5]) (+) + +// flip :: (a -> b -> c) -> b -> a -> c +// f :: a -> b -> c -> d -> e +// flip f :: b -> a -> c -> d -> e diff --git a/library/core/src/ctrl/monad.fe b/library/core/src/ctrl/monad.fe new file mode 100644 index 000000000..e7ddafe88 --- /dev/null +++ b/library/core/src/ctrl/monad.fe @@ -0,0 +1,121 @@ +use ingot::num::arith::HAdd +use ingot::ctrl::{functor::Functor, function::Fn} +use ingot::data::tuple::Tuple + +pub trait Monad: Functor +where Self: * -> * +{ + fn bind(self: Self, morph: Morph) -> Self + where Morph: Fn<1, (Source), Self>, (Source): Tuple<1> +} + + +// impl HAdd> for Option { +// fn add(self, rhs: u8) -> Option { +// self.bind>(morph: BindAdd { n: rhs }) +// } +// } + +// fn test_monadd() { +// let a: Option = Option::Some(42) +// let b = 26 +// let c = a.add(rhs: b) +// } + +// type MyFn = () + +// impl Fn<1, (bool), Option> for MyFn { +// fn exec(self, args: (bool)) -> Option { +// Option::Some(0) +// } +// } + +// impl Tuple<1> for (bool) { } + +// #test +// fn my_test() { +// let f: MyFn = () +// let a = Option::Some(true).bind(f) +// } + +// fn map(t: T, f: F) -> U +// where F: Fn(T) -> U {...} + +// type MyFn = () + +// impl Fn for Foo { +// fn exec(&self, t: T) -> U { +// t.element(0) +// t.len() +// } +// } + +// impl Fn<(u8, u8>, Option> for MyFn { +// fn exec(t: (bool, bool)) -> Option { +// let (a, b) = t +// f(a, b) +// } +// } + +// sub x y = x - y +// f = sub 1 // f 2 == 1 - 2 +// g = `sub` 1 // g 2 == 2 - 1 + + +// enum Result { +// Ok(T) +// Err(E) +// } +// impl Functor for Result<*, E> { // or Result<_, E> maybe? +// fn map>(self: Self, _ f: F) -> Self { +// match self { +// Result::Ok(a) => { +// return Result::Ok(f(a)) +// } +// Result::Err(e) => { +// return Result::Err(e) +// } +// } +// } +// } + + +// enum Res { // Result +// Err(E) +// Ok(T) +// } +// impl Functor for Res { +// fn map>(self: Self, _ f: F) -> Self { +// match self { +// Result::Ok(a) => { +// return Result::Ok(f(a)) +// } +// Result::Err(e) => { +// return Result::Err(e) +// } +// } +// } +// } + + + +// fn main() { +// let r = foo() +// r.map(|t| ...) +// } + + +// enum Result1 + +// Result<_, E> + +// Flip (Result) + + + +// ((+) `foldl` 0) [1..5] +// ((`foldl` 0) [1..5]) (+) + +// flip :: (a -> b -> c) -> b -> a -> c +// f :: a -> b -> c -> d -> e +// flip f :: b -> a -> c -> d -> e diff --git a/library/core/src/ctrl/monad/option.fe b/library/core/src/ctrl/monad/option.fe new file mode 100644 index 000000000..73cc81d80 --- /dev/null +++ b/library/core/src/ctrl/monad/option.fe @@ -0,0 +1,13 @@ +use ingot::ctrl::{monad::Monad, function::Fn} +use ingot::data::{option::Option, tuple::Tuple} + +impl Monad for Option { + fn bind(self: Self, morph: Morph) -> Self + where Morph: Fn<1, (Source), Self>, (Source): Tuple<1> + { + match self { + Self::Some(self) => morph.exec(args: (self, )) + Self::None => Self::None + } + } +} diff --git a/library/core/src/data.fe b/library/core/src/data.fe new file mode 100644 index 000000000..e69de29bb diff --git a/library/core/src/data/list.fe b/library/core/src/data/list.fe new file mode 100644 index 000000000..ff7bc3519 --- /dev/null +++ b/library/core/src/data/list.fe @@ -0,0 +1,4 @@ +trait List { + fn list_get(self, index: N) -> Value + fn list_set(mut self, index: N, value: Value) +} \ No newline at end of file diff --git a/library/core/src/data/map.fe b/library/core/src/data/map.fe new file mode 100644 index 000000000..0ace7e716 --- /dev/null +++ b/library/core/src/data/map.fe @@ -0,0 +1,4 @@ +trait List { + fn map_get(self, key: Key) -> Value + fn map_set(mut self, key: Key, value: Value) +} \ No newline at end of file diff --git a/library/core/src/data/option.fe b/library/core/src/data/option.fe new file mode 100644 index 000000000..b6b588295 --- /dev/null +++ b/library/core/src/data/option.fe @@ -0,0 +1,4 @@ +pub enum Option { + Some(Value), + None +} \ No newline at end of file diff --git a/library/core/src/data/result.fe b/library/core/src/data/result.fe new file mode 100644 index 000000000..9e69fcea0 --- /dev/null +++ b/library/core/src/data/result.fe @@ -0,0 +1,4 @@ +pub enum Result { + Ok(Ok), + Err(Err), +} \ No newline at end of file diff --git a/library/core/src/data/set.fe b/library/core/src/data/set.fe new file mode 100644 index 000000000..e69de29bb diff --git a/library/core/src/data/string.fe b/library/core/src/data/string.fe new file mode 100644 index 000000000..e69de29bb diff --git a/library/core/src/data/tuple.fe b/library/core/src/data/tuple.fe new file mode 100644 index 000000000..1fed8896f --- /dev/null +++ b/library/core/src/data/tuple.fe @@ -0,0 +1 @@ +pub trait Tuple { } \ No newline at end of file diff --git a/library/core/src/io.fe b/library/core/src/io.fe new file mode 100644 index 000000000..1af044076 --- /dev/null +++ b/library/core/src/io.fe @@ -0,0 +1,15 @@ +trait Read { + fn read(self) -> Out +} + +trait Write { + fn write(mut self, value: In) +} + +trait Encode> { + fn encode(mut self, mut w: W) +} + +trait Decode> { + fn decode(mut self, mut r: R) -> Self +} \ No newline at end of file diff --git a/library/core/src/lib.fe b/library/core/src/lib.fe new file mode 100644 index 000000000..e69de29bb diff --git a/library/core/src/num.fe b/library/core/src/num.fe new file mode 100644 index 000000000..1d75fe8fe --- /dev/null +++ b/library/core/src/num.fe @@ -0,0 +1,25 @@ +use self::arith::{Add, Sub, Mul, Div, Neg, Mod, Pow} +use ingot::ctrl::monad::Monad + +pub trait Num: Add + Sub + Mul + Div + Pow { } + +pub trait Complex: Num + Neg { + fn re() -> N + fn im() -> N +} + +pub trait Real: Num + Neg { } + +pub trait Frac: Num + Neg { + fn nu() -> N + fn de() -> N +} + +pub trait Int: Num + Mod + Neg { } + +pub trait Nat: Num + Mod { } + +// impl *> Num for M +// where M: Monad, N: Num { } + +impl Num for u8 { } \ No newline at end of file diff --git a/library/core/src/num/arith.fe b/library/core/src/num/arith.fe new file mode 100644 index 000000000..2b4b5b2fd --- /dev/null +++ b/library/core/src/num/arith.fe @@ -0,0 +1,78 @@ +/// Addition (e.g. `x + y`) +pub trait HAdd { + fn add(self, rhs: Rhs) -> Out +} + +/// Subtraction (e.g. `x - y`) +pub trait HSub { + fn sub(self, rhs: Rhs) -> Out +} + +/// Multiplication (e.g. `x * y`) +pub trait HMul { + fn mul(self, rhs: Rhs) -> Out +} + +/// Division (e.g. `x / y`) +pub trait HDiv { + fn div(self, rhs: Rhs) -> Out +} + +/// Modulo (e.g. `x % y`) +pub trait HMod { + fn modulo(self, rhs: Rhs) -> Out +} + +/// Power (e.g. `x ** y`) +pub trait HPow { + fn pow(self, rhs: Rhs) -> Out +} + +/// Neg (e.g. `-x`) +pub trait HNeg { + fn neg(self) -> Out +} + +pub trait Add: HAdd { } + +pub trait Sub: HSub { } + +pub trait Mul: HMul { } + +pub trait Div: HDiv { } + +pub trait Pow: HPow { } + +pub trait Mod: HMod { } + +pub trait Neg: HNeg { } + +struct BindAdd { n: N } + +impl HAdd for i8 { fn add(self, rhs: Self) -> Self { self + rhs } } +impl HSub for i8 { fn sub(self, rhs: Self) -> Self { self - rhs } } +impl HMul for i8 { fn mul(self, rhs: Self) -> Self { self * rhs } } +impl HDiv for i8 { fn div(self, rhs: Self) -> Self { self / rhs } } +impl HPow for i8 { fn pow(self, rhs: Self) -> Self { self ** rhs } } +impl HNeg for i8 { fn neg(self) -> Self { -self } } + +impl Add for i8 { } +impl Sub for i8 { } +impl Mul for i8 { } +impl Div for i8 { } +impl Pow for i8 { } +impl Neg for i8 { } + +impl HAdd for u8 { fn add(self, rhs: Self) -> Self { self + rhs } } +impl HSub for u8 { fn sub(self, rhs: Self) -> Self { self - rhs } } +impl HMul for u8 { fn mul(self, rhs: Self) -> Self { self * rhs } } +impl HDiv for u8 { fn div(self, rhs: Self) -> Self { self / rhs } } +impl HPow for u8 { fn pow(self, rhs: Self) -> Self { self ** rhs } } +impl HNeg for u8 { fn neg(self) -> Self { -self } } + +impl Add for u8 { } +impl Sub for u8 { } +impl Mul for u8 { } +impl Div for u8 { } +impl Pow for u8 { } +impl Neg for u8 { } diff --git a/library/core/src/num/nat.fe b/library/core/src/num/nat.fe new file mode 100644 index 000000000..03656fe05 --- /dev/null +++ b/library/core/src/num/nat.fe @@ -0,0 +1,15 @@ +// impl *, N> Fn<1, (N), M> for BindAdd +// where M: Monad, N: HAdd, (N): Tuple<1> +// { +// fn exec(self, args: (N)) -> M { +// M::pure(t: args.0.add(rhs: self.n)) +// } +// } + +// impl *, N> HAdd> for M +// where M: Monad, N: HAdd, (N): Tuple<1> +// { +// fn add(self, rhs: N) -> M { +// self.bind>(morph: BindAdd { n: rhs }) +// } +// } diff --git a/library/eth/fe.toml b/library/eth/fe.toml new file mode 100644 index 000000000..7576ea110 --- /dev/null +++ b/library/eth/fe.toml @@ -0,0 +1,3 @@ +[package] +name = "eth" +version = "1.0.0" \ No newline at end of file diff --git a/library/eth/src/abi.fe b/library/eth/src/abi.fe new file mode 100644 index 000000000..e69de29bb diff --git a/library/eth/src/contract.fe b/library/eth/src/contract.fe new file mode 100644 index 000000000..ef342faaa --- /dev/null +++ b/library/eth/src/contract.fe @@ -0,0 +1,18 @@ +trait Contract { + fn init(buf: CallBuffer) -> Self + fn recv(self, buf: CallBuffer) -> MemBuffer +} + +struct Foo { + f1: u8, + f2: bool, + f3: Data +} + +impl Contract for Foo { + fn init(buf: CallBuffer) -> Self { + let f1 = buf.read() + let f2 = buf.read() + Self { f1, f2, } + } +} \ No newline at end of file diff --git a/library/eth/src/lib.fe b/library/eth/src/lib.fe new file mode 100644 index 000000000..e69de29bb diff --git a/library/std/fe.toml b/library/std/fe.toml new file mode 100644 index 000000000..3cbc2c278 --- /dev/null +++ b/library/std/fe.toml @@ -0,0 +1,3 @@ +[package] +name = "std" +version = "1.0.0" \ No newline at end of file diff --git a/library/std/src/data/list.fe b/library/std/src/data/list.fe new file mode 100644 index 000000000..fe85b0249 --- /dev/null +++ b/library/std/src/data/list.fe @@ -0,0 +1 @@ +// use ingot::target::evm::{alloc} \ No newline at end of file diff --git a/library/std/src/lib.fe b/library/std/src/lib.fe new file mode 100644 index 000000000..e69de29bb diff --git a/library/std/src/target/evm.fe b/library/std/src/target/evm.fe new file mode 100644 index 000000000..8421e445b --- /dev/null +++ b/library/std/src/target/evm.fe @@ -0,0 +1,10 @@ +// struct MemBuf { +// fn read() -> +// fn write() +// } + +// extern { +// alloc(size: usize) -> ??????? +// } + +