diff --git a/src/fun/mod.rs b/src/fun/mod.rs index ccdeeec22..282e630ed 100644 --- a/src/fun/mod.rs +++ b/src/fun/mod.rs @@ -1,6 +1,6 @@ use crate::{ diagnostics::{Diagnostics, DiagnosticsConfig}, - imports::ImportType, + imports::Import, maybe_grow, multi_iterator, ENTRY_POINT, }; use indexmap::{IndexMap, IndexSet}; @@ -57,7 +57,7 @@ pub struct Book { pub entrypoint: Option, /// Imports declared in the program. - pub imports: Vec<(Name, ImportType)>, + pub imports: Vec, } pub type Definitions = IndexMap; diff --git a/src/fun/parser.rs b/src/fun/parser.rs index 881906589..bffa57a5c 100644 --- a/src/fun/parser.rs +++ b/src/fun/parser.rs @@ -6,11 +6,12 @@ use crate::{ Name, Num, Op, Pattern, Rule, Source, Tag, Term, STRINGS, }, imp::{parser::PyParser, Enum, Variant}, - imports::{ImportType, Imports}, + imports::{Import, ImportCtx, ImportType}, maybe_grow, }; use highlight_error::highlight_error; use indexmap::IndexMap; +use itertools::Itertools; use TSPL::Parser; type FunDefinition = super::Definition; @@ -35,7 +36,7 @@ pub struct ParseBook { pub ctrs: Constructors, /// Imported packages to be loaded in the program - pub imports: Imports, + pub import_ctx: ImportCtx, /// Source of the book pub source: Name, @@ -178,10 +179,21 @@ impl<'a> TermParser<'a> { } // Import declaration - if self.try_parse_keyword("use") { + if self.try_parse_keyword("from") { self.skip_trivia(); - let (import, sub_imports) = self.parse_import()?; - book.imports.add_import(import, sub_imports); + let import = self.parse_from_import()?; + book.import_ctx.add_import(import); + indent = self.advance_newlines()?; + last_rule = None; + continue; + } + + if self.try_parse_keyword("import") { + self.skip_trivia(); + let imports = self.parse_import()?; + for imp in imports { + book.import_ctx.add_import(imp); + } indent = self.advance_newlines()?; last_rule = None; continue; @@ -260,28 +272,52 @@ impl<'a> TermParser<'a> { Ok(def) } - fn parse_import(&mut self) -> Result<(Name, ImportType), String> { - // use package - let (import, alias) = self.parse_name_maybe_alias("Import")?; + fn parse_from_import(&mut self) -> Result { + // from path import package + // from path import (a, b) + // from path import * + let path = self.parse_restricted_name("Path")?; + self.consume("import")?; + + let relative = path.starts_with("./") | path.starts_with("../"); - if let Some(alias) = alias { - return Ok((import, ImportType::Simple(Some(alias)))); + if self.try_consume("*") { + return Ok(Import::new(path, ImportType::Glob, relative)); } - if self.try_consume("{") { - if self.try_consume("*") { - self.consume("}")?; - return Ok((import, ImportType::Glob)); - } + if self.try_consume("(") { + let sub = self.list_like(|p| p.parse_name_maybe_alias("Name"), "", ")", ",", false, 1)?; + return Ok(Import::new(path, ImportType::List(sub), relative)); + } + + let (import, alias) = self.parse_name_maybe_alias("Import")?; + Ok(Import::new(path, ImportType::Simple(import, alias), relative)) + } + + fn parse_import(&mut self) -> Result, String> { + // import path + // import (path/a, path/b) + + let new_import = |import: Name, alias: Option, relative: bool| -> Import { + let (path, import) = match import.rsplit_once('/') { + Some((start, end)) => (Name::new(start), Name::new(end)), + None => (Name::default(), import), + }; - let sub = self.list_like(|p| p.parse_name_maybe_alias("Name"), "", "}", ",", false, 0)?; - let imp_type = if sub.is_empty() { ImportType::Simple(None) } else { ImportType::List(sub) }; + Import::new(path, ImportType::Simple(import, alias), relative) + }; - return Ok((import, imp_type)); + if self.try_consume("(") { + let list = self.list_like(|p| p.parse_import_name("Name"), "", ")", ",", false, 1)?; + let imports = list.into_iter().map(|(a, b, c)| new_import(a, b, c)).collect_vec(); + return Ok(imports); } - Ok((import, ImportType::Simple(None))) + let (import, alias, relative) = self.parse_import_name("Import")?; + let import = new_import(import, alias, relative); + Ok(vec![import]) } + fn parse_rule(&mut self) -> ParseResult<(Name, Rule)> { // (name pat*) = term // name pat* = term @@ -1093,6 +1129,12 @@ pub trait ParserCommons<'a>: Parser<'a> { } } + fn parse_import_name(&mut self, label: &str) -> Result<(Name, Option, bool), String> { + let (import, alias) = self.parse_name_maybe_alias(label)?; + let relative = import.starts_with("./") | import.starts_with("../"); + Ok((import, alias, relative)) + } + /// Consumes exactly the text without skipping. fn consume_exactly(&mut self, text: &str) -> ParseResult<()> { if self.input().get(*self.index()..).unwrap_or_default().starts_with(text) { diff --git a/src/imp/to_fun.rs b/src/imp/to_fun.rs index 4b345b760..591240eea 100644 --- a/src/imp/to_fun.rs +++ b/src/imp/to_fun.rs @@ -19,8 +19,8 @@ impl ParseBook { self.fun_defs.insert(name, def.to_fun(source)?); } - let ParseBook { fun_defs: defs, hvm_defs, adts, ctrs, imports, .. } = self; - Ok(Book { defs, hvm_defs, adts, ctrs, entrypoint: None, imports: imports.to_names() }) + let ParseBook { fun_defs: defs, hvm_defs, adts, ctrs, import_ctx, .. } = self; + Ok(Book { defs, hvm_defs, adts, ctrs, entrypoint: None, imports: import_ctx.to_imports() }) } } diff --git a/src/imports.rs b/src/imports.rs index 05aafda61..384ae0790 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -7,38 +7,79 @@ use indexmap::{map::Entry, IndexMap}; use itertools::Itertools; use std::{ collections::{HashSet, VecDeque}, - path::PathBuf, + fmt::Display, + path::{Path, PathBuf}, }; #[derive(Debug, Clone, Default)] -pub struct Imports { +pub struct ImportCtx { /// Imports declared in the program source. - names: Vec<(Name, ImportType)>, + imports: Vec, /// Map from bound names to source package. map: ImportsMap, - - /// Imported packages names. - pkgs: Vec, } -impl Imports { - pub fn add_import(&mut self, import: Name, import_type: ImportType) { - self.names.push((import, import_type)); +impl ImportCtx { + pub fn add_import(&mut self, import: Import) { + self.imports.push(import); + } + + pub fn to_imports(self) -> Vec { + self.imports } - pub fn to_names(self) -> Vec<(Name, ImportType)> { - self.names + pub fn sources(&self) -> Vec<&Name> { + let mut names = Vec::new(); + for imps in &self.imports { + match &imps.src { + BoundSource::None => todo!(), + BoundSource::File(f) => names.push(f), + BoundSource::Folder(v) => names.extend(v), + } + } + names + } +} + +#[derive(Debug, Clone)] +pub struct Import { + path: Name, + imp_type: ImportType, + relative: bool, + src: BoundSource, +} + +#[derive(Debug, Clone)] +pub enum BoundSource { + None, + File(Name), + Folder(Vec), +} + +impl Import { + pub fn new(path: Name, imp_type: ImportType, relative: bool) -> Self { + Self { path, imp_type, relative, src: BoundSource::None } } } #[derive(Debug, Clone)] pub enum ImportType { - Simple(Option), + Simple(Name, Option), List(Vec<(Name, Option)>), Glob, } +impl Display for ImportType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ImportType::Simple(n, _) => write!(f, "{n}"), + ImportType::List(l) => write!(f, "({})", l.iter().map(|(n, _)| n).join(", ")), + ImportType::Glob => write!(f, "*"), + } + } +} + #[derive(Debug, Clone, Default)] struct ImportsMap { binds: IndexMap, @@ -116,59 +157,52 @@ impl Packages { dir: Option, loader: &mut impl PackageLoader, ) -> Result<(), Diagnostics> { - let names = self.get_book(idx).imports.names.clone(); + let names = &mut self.get_book_mut(idx).import_ctx.imports; + let mut sources = IndexMap::new(); - for (src, imp_type) in names { - // TODO: Would this be correct when handling non-local imports? Do we want relative online sources? - // TODO: Normalize paths when using `..` - let src = dir.as_ref().map_or(src.clone(), |dir| Name::new(format!("{}/{}", dir, src))); - - let mut sources = IndexMap::new(); - let packages = loader.load(src.clone(), &imp_type, &mut sources)?; + for import in names { + if import.relative { + if let Some(ref dir) = dir { + import.path = Name::new(format!("{}/{}", dir, import.path)); + } + } - self.get_book_mut(idx).imports.pkgs.extend(packages); + let loaded = loader.load(import)?; + sources.extend(loaded); + } - for (psrc, code) in sources { - let module = do_parse_book(&code, &psrc, ParseBook::default())?; + for (psrc, code) in sources { + let module = do_parse_book(&code, &psrc, ParseBook::default())?; - self.load_queue.push_back(self.books.len()); - self.books.insert(psrc, module); - } + self.load_queue.push_back(self.books.len()); + self.books.insert(psrc, module); } + Ok(()) } fn load_binds(&mut self, idx: usize, diag: &mut Diagnostics) { let book = self.get_book(idx); - let pkgs = book.imports.pkgs.iter(); - let names = book.imports.names.iter(); - let binds = pkgs.zip(names).map(|(src, (_, imp))| (src.clone(), imp.clone())).collect_vec(); + let imports = book.import_ctx.imports.clone(); - for (src, imp_type) in binds { - match imp_type { - ImportType::Simple(alias) => { + for Import { imp_type, src: pkgs, .. } in imports { + match (pkgs, imp_type) { + (BoundSource::File(src), ImportType::Simple(nam, alias)) => { let bound_book = self.books.get(&src).unwrap(); - let names: HashSet<_> = bound_book.top_level_names().cloned().collect(); - let pkg_name = Name::new(src.split('/').last().unwrap()); - let aliased = alias.as_ref().unwrap_or(&pkg_name); + if !bound_book.top_level_names().contains(&nam) { + let err = format!("Package '{src}' does not contain the top level name '{nam}'"); + diag.add_book_error(err); + } let book = self.get_book_mut(idx); - for name in &names { - if name != &pkg_name { - let src = format!("{}/{}", src, name); - let bind = Name::new(format!("{aliased}/{name}")); - book.imports.map.add_bind(bind, &src, diag); - } - } - - if names.contains(&pkg_name) { - let src = format!("{}/{}", src, pkg_name); - book.imports.map.add_bind(aliased.clone(), &src, diag); - } + let src = format!("{}/{}", src, nam); + let aliased = alias.unwrap_or(nam); + book.import_ctx.map.add_bind(aliased, &src, diag); } - ImportType::List(names) => { + + (BoundSource::File(src), ImportType::List(names)) => { let bound_book = self.books.get(&src).unwrap(); for (sub, _) in &names { @@ -183,10 +217,11 @@ impl Packages { for (sub, alias) in names { let src = format!("{}/{}", src, sub); let aliased = alias.unwrap_or(sub); - book.imports.map.add_bind(aliased, &src, diag); + book.import_ctx.map.add_bind(aliased, &src, diag); } } - ImportType::Glob => { + + (BoundSource::File(src), ImportType::Glob) => { let bound_book = self.books.get(&src).unwrap(); let names: HashSet<_> = bound_book.top_level_names().cloned().collect(); @@ -194,12 +229,54 @@ impl Packages { for sub in names { let src = format!("{}/{}", src, sub); - book.imports.map.add_bind(sub, &src, diag); + book.import_ctx.map.add_bind(sub, &src, diag); + } + } + + (BoundSource::Folder(mut src), ImportType::Simple(nam, alias)) => { + let src = src.pop().unwrap(); + self.add_book_bind(idx, src, nam, alias, diag); + } + + (BoundSource::Folder(pkgs), ImportType::List(names)) => { + for (src, (nam, alias)) in pkgs.into_iter().zip_eq(names) { + self.add_book_bind(idx, src, nam, alias, diag); } } + + (BoundSource::Folder(pkgs), ImportType::Glob) => { + for src in pkgs { + let nam = Name::new(src.split('/').last().unwrap()); + self.add_book_bind(idx, src, nam, None, diag); + } + } + + (BoundSource::None, _) => unreachable!(), } } } + + fn add_book_bind(&mut self, idx: usize, src: Name, nam: Name, alias: Option, diag: &mut Diagnostics) { + let bound_book = self.books.get(&src).unwrap(); + let names: HashSet<_> = bound_book.top_level_names().cloned().collect(); + + let aliased = alias.as_ref().unwrap_or(&nam); + + let book = self.get_book_mut(idx); + + for name in &names { + if name != &nam { + let src = format!("{}/{}", src, name); + let bind = Name::new(format!("{aliased}/{name}")); + book.import_ctx.map.add_bind(bind, &src, diag); + } + } + + if names.contains(&nam) { + let src = format!("{}/{}", src, nam); + book.import_ctx.map.add_bind(aliased.clone(), &src, diag); + } + } } impl ParseBook { @@ -241,12 +318,14 @@ impl ParseBook { ) -> Result<(), Diagnostics> { diag.start_pass(); - for src in self.imports.pkgs.clone() { + let sources = self.import_ctx.sources().into_iter().cloned().collect_vec(); + + for src in sources { let Some(mut package) = pkgs.books.swap_remove(&src) else { continue }; // Can not be done outside the loop/function because of the borrow checker. // Just serves to pass only the import map of the first call to `apply_imports_go`. - let main_imports = main_imports.unwrap_or(&self.imports.map); + let main_imports = main_imports.unwrap_or(&self.import_ctx.map); package.apply_imports(Some(main_imports), diag, pkgs)?; let new_adts = package.apply_adts(&src, main_imports); @@ -279,12 +358,12 @@ impl ParseBook { ) { // Can not be done outside the function because of the borrow checker. // Just serves to pass only the import map of the first call to `apply_imports_go`. - let main_imports = main_imports.unwrap_or(&self.imports.map); + let main_imports = main_imports.unwrap_or(&self.import_ctx.map); let mut local_imports: IndexMap = IndexMap::new(); // Collect local imports binds, starting with `__` if not imported by the main book. - 'outer: for (bind, src) in self.imports.map.iter().rev() { + 'outer: for (bind, src) in self.import_ctx.map.iter().rev() { if self.contains_def(bind) | self.ctrs.contains_key(bind) | self.adts.contains_key(bind) { // TODO: Here we should show warnings for shadowing of imported names by local def/ctr/adt // It can be done, but when importing with `ImportType::Simple` files in the same folder, @@ -302,7 +381,7 @@ impl ParseBook { continue; } - for pkg in &self.imports.pkgs { + for pkg in self.import_ctx.sources() { if let Some(book) = pkgs.loaded_adts.get(pkg) { if let Some(ctrs) = book.get(&nam) { for ctr in ctrs.iter().rev() { @@ -534,33 +613,121 @@ impl Stmt { type Sources = IndexMap; pub trait PackageLoader { - fn load(&mut self, name: Name, import_type: &ImportType, pkgs: &mut Sources) -> Result, String>; + fn load(&mut self, import: &mut Import) -> Result; fn is_loaded(&self, name: &Name) -> bool; } pub struct DefaultLoader { - pub local_path: PathBuf, - pub loaded: HashSet, + local_path: PathBuf, + loaded: HashSet, } impl DefaultLoader { - pub fn new(local_path: PathBuf) -> Self { + pub fn new(local_path: &Path) -> Self { + let local_path = local_path.parent().unwrap().to_path_buf(); Self { local_path, loaded: HashSet::new() } } + + fn read_file(&mut self, path: &Path, file: Name, src: &mut Sources) -> Option { + if !self.is_loaded(&file) { + self.loaded.insert(file.clone()); + + let path = path.with_extension("bend"); + let code = std::fs::read_to_string(path).ok()?; + src.insert(file.clone(), code); + } + Some(file) + } + + fn read_file_in_folder( + &mut self, + full_path: &Path, + folder: &str, + file_name: &str, + src: &mut Sources, + ) -> Option { + let file_path = Name::new(format!("{}/{}", folder, file_name)); + let full_path = full_path.join(file_name); + + self.read_file(&full_path, file_path, src) + } + + fn read_path( + &mut self, + base_path: &Path, + path: &Name, + imp_type: &ImportType, + ) -> Option<(BoundSource, Sources)> { + let full_path = base_path.join(path.as_ref()); + let mut src = IndexMap::new(); + + if full_path.with_extension("bend").is_file() { + if let Some(nam) = self.read_file(&full_path, path.clone(), &mut src) { + return Some((BoundSource::File(nam), src)); + } + } + + if full_path.is_dir() || path.is_empty() { + let mut names = Vec::new(); + + match imp_type { + ImportType::Simple(file, _) => { + let name = self.read_file_in_folder(&full_path, path, file, &mut src)?; + names.push(name); + } + ImportType::List(list) => { + for (file, _) in list { + let name = self.read_file_in_folder(&full_path, path, file, &mut src)?; + names.push(name); + } + } + ImportType::Glob => { + for entry in full_path.read_dir().unwrap().flatten() { + let file = PathBuf::from(&entry.file_name()); + + if let Some("bend") = file.extension().and_then(|f| f.to_str()) { + let file = file.file_stem().unwrap().to_string_lossy(); + let name = self.read_file_in_folder(&full_path, path, &file, &mut src)?; + names.push(name); + } + } + } + } + + return Some((BoundSource::Folder(names), src)); + } + + None + } } +pub const PATH: &[&str] = &[".bend"]; + impl PackageLoader for DefaultLoader { - fn load(&mut self, name: Name, _import_type: &ImportType, pkgs: &mut Sources) -> Result, String> { - if !self.is_loaded(&name) { - // TODO: Should the local filesystem be searched anyway for each sub_name? - // TODO: If the name to load is a folder, and we have sub names, we should load those files instead? - self.loaded.insert(name.clone()); - let path = self.local_path.parent().unwrap().join(name.as_ref()).with_extension("bend"); - let code = std::fs::read_to_string(path).map_err(|e| e.to_string())?; - pkgs.insert(name.clone(), code); + fn load(&mut self, import: &mut Import) -> Result { + let mut sources = Sources::new(); + + let Import { path, imp_type, relative, src } = import; + + let folders = if *relative { + vec![self.local_path.clone()] + } else { + PATH.iter().map(|p| self.local_path.join(p)).collect() + }; + + for base in folders { + let Some((names, new_pkgs)) = self.read_path(&base, path, imp_type) else { continue }; + + *src = names; + sources.extend(new_pkgs); + break; + } + + if let BoundSource::None = src { + return Err(format!("Failed to import '{}' from '{}'", imp_type, path).to_string()); } - Ok(vec![name]) + Ok(sources) } fn is_loaded(&self, name: &Name) -> bool { diff --git a/src/main.rs b/src/main.rs index 387167922..b6fdcd315 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,7 +8,6 @@ use bend::{ }; use clap::{Args, CommandFactory, Parser, Subcommand}; use std::{ - collections::HashSet, path::{Path, PathBuf}, process::ExitCode, }; @@ -254,7 +253,7 @@ fn execute_cli_mode(mut cli: Cli) -> Result<(), Diagnostics> { let entrypoint = cli.entrypoint.take(); let load_book = |path: &Path, diag: DiagnosticsConfig| -> Result { - let package_loader = DefaultLoader { local_path: path.to_path_buf(), loaded: HashSet::new() }; + let package_loader = DefaultLoader::new(path); let mut book = load_file_to_book(path, package_loader, diag)?; book.entrypoint = entrypoint.map(Name::new); diff --git a/tests/golden_tests.rs b/tests/golden_tests.rs index 15fb16495..21f2bf70c 100644 --- a/tests/golden_tests.rs +++ b/tests/golden_tests.rs @@ -199,7 +199,7 @@ fn import_system() { ..DiagnosticsConfig::new(Severity::Error, true) }; - let book = load_to_book(path.display(), code, DefaultLoader::new(path.to_path_buf()), diagnostics_cfg)?; + let book = load_to_book(path.display(), code, DefaultLoader::new(path), diagnostics_cfg)?; let run_opts = RunOpts::default(); let mut res = String::new(); diff --git a/tests/golden_tests/import_system/lib/a.bend b/tests/golden_tests/import_system/.bend/lib/a.bend similarity index 100% rename from tests/golden_tests/import_system/lib/a.bend rename to tests/golden_tests/import_system/.bend/lib/a.bend diff --git a/tests/golden_tests/import_system/lib/a/b.bend b/tests/golden_tests/import_system/.bend/lib/a/b.bend similarity index 100% rename from tests/golden_tests/import_system/lib/a/b.bend rename to tests/golden_tests/import_system/.bend/lib/a/b.bend diff --git a/tests/golden_tests/import_system/lib/bool_xor.bend b/tests/golden_tests/import_system/.bend/lib/bool_xor.bend similarity index 81% rename from tests/golden_tests/import_system/lib/bool_xor.bend rename to tests/golden_tests/import_system/.bend/lib/bool_xor.bend index 1af9a2117..0d14cec64 100644 --- a/tests/golden_tests/import_system/lib/bool_xor.bend +++ b/tests/golden_tests/import_system/.bend/lib/bool_xor.bend @@ -1,4 +1,4 @@ -use types{Bool} +from lib/types import Bool (bool_xor Bool/True Bool/False) = Bool/True (bool_xor Bool/False Bool/True) = Bool/True diff --git a/tests/golden_tests/import_system/lib/defs.bend b/tests/golden_tests/import_system/.bend/lib/defs.bend similarity index 100% rename from tests/golden_tests/import_system/lib/defs.bend rename to tests/golden_tests/import_system/.bend/lib/defs.bend diff --git a/tests/golden_tests/import_system/lib/folder/myFun.bend b/tests/golden_tests/import_system/.bend/lib/folder/myFun.bend similarity index 100% rename from tests/golden_tests/import_system/lib/folder/myFun.bend rename to tests/golden_tests/import_system/.bend/lib/folder/myFun.bend diff --git a/tests/golden_tests/import_system/lib/myFun.bend b/tests/golden_tests/import_system/.bend/lib/myFun.bend similarity index 100% rename from tests/golden_tests/import_system/lib/myFun.bend rename to tests/golden_tests/import_system/.bend/lib/myFun.bend diff --git a/tests/golden_tests/import_system/lib/nums.bend b/tests/golden_tests/import_system/.bend/lib/nums.bend similarity index 100% rename from tests/golden_tests/import_system/lib/nums.bend rename to tests/golden_tests/import_system/.bend/lib/nums.bend diff --git a/tests/golden_tests/import_system/lib/types.bend b/tests/golden_tests/import_system/.bend/lib/types.bend similarity index 100% rename from tests/golden_tests/import_system/lib/types.bend rename to tests/golden_tests/import_system/.bend/lib/types.bend diff --git a/tests/golden_tests/import_system/import_types.bend b/tests/golden_tests/import_system/import_types.bend index de82bc33d..38b531ee1 100644 --- a/tests/golden_tests/import_system/import_types.bend +++ b/tests/golden_tests/import_system/import_types.bend @@ -1,5 +1,5 @@ -use lib/types{Bool, MyTree} -use lib/bool_xor +from lib/types import (Bool, MyTree) +from lib import bool_xor def tree_xor(tree): fold tree: diff --git a/tests/golden_tests/import_system/imports.bend b/tests/golden_tests/import_system/imports.bend index 58a010beb..b80ac5d98 100644 --- a/tests/golden_tests/import_system/imports.bend +++ b/tests/golden_tests/import_system/imports.bend @@ -1,5 +1,5 @@ -use lib/nums{one, two} -use lib/defs{sum} +from lib/nums import (one, two) +from lib/defs import sum def main(): return sum(one, two) \ No newline at end of file diff --git a/tests/golden_tests/import_system/imports_alias.bend b/tests/golden_tests/import_system/imports_alias.bend index c585bec24..a23f95304 100644 --- a/tests/golden_tests/import_system/imports_alias.bend +++ b/tests/golden_tests/import_system/imports_alias.bend @@ -1,5 +1,5 @@ -use lib/nums{one as One, two as Two} -use lib/defs{sum as summation} +from lib/nums import (one as One, two as Two) +from lib/defs import (sum as summation) def main(): return summation(One, Two) \ No newline at end of file diff --git a/tests/golden_tests/import_system/imports_alias_shadow.bend b/tests/golden_tests/import_system/imports_alias_shadow.bend index e0ff993ac..f9cc3fbdc 100644 --- a/tests/golden_tests/import_system/imports_alias_shadow.bend +++ b/tests/golden_tests/import_system/imports_alias_shadow.bend @@ -1,4 +1,4 @@ -use lib/nums{one as A, two as A} +from lib/nums import (one as A, two as A) def main(): return A + A \ No newline at end of file diff --git a/tests/golden_tests/import_system/imports_conflict.bend b/tests/golden_tests/import_system/imports_conflict.bend index 7af6b32e5..dd186ecc7 100644 --- a/tests/golden_tests/import_system/imports_conflict.bend +++ b/tests/golden_tests/import_system/imports_conflict.bend @@ -1,5 +1,5 @@ -use lib/a/b{C} -use lib/a{b/C} +from lib/a/b import C +from lib/a import b/C lib/a/b/C = * diff --git a/tests/golden_tests/import_system/imports_shadow.bend b/tests/golden_tests/import_system/imports_shadow.bend index 1294fca98..83c72fa2f 100644 --- a/tests/golden_tests/import_system/imports_shadow.bend +++ b/tests/golden_tests/import_system/imports_shadow.bend @@ -1,5 +1,5 @@ -use lib/folder/myFun -use lib/myFun +from lib/folder import myFun +from lib import myFun def main(): return myFun \ No newline at end of file diff --git a/tests/golden_tests/import_system/imports_shadow2.bend b/tests/golden_tests/import_system/imports_shadow2.bend index e73e0ec2e..c0b1c26c2 100644 --- a/tests/golden_tests/import_system/imports_shadow2.bend +++ b/tests/golden_tests/import_system/imports_shadow2.bend @@ -1,5 +1,5 @@ -use lib/myFun -use lib/folder/myFun +from lib import myFun +from lib/folder import myFun def main(): return myFun(lib/myFun/myFun) # use the full name to call a shadowed imported def \ No newline at end of file