Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A64 Fix: Amber imports must be namespaced #40

Merged
merged 3 commits into from
Oct 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions setup/install.ab
Original file line number Diff line number Diff line change
Expand Up @@ -20,36 +20,36 @@ let url = 'https://github.com/Ph0enixKM/{name}/releases/download/{tag}/amber_{os
$test -d "{place}" > /dev/null$

if $echo \$?$ == '0' {
$echo "Amber already installed" $
$echo "It seems that Amber is already installed on your system."$
$echo "If you want to reinstall Amber - try to uninstall it first."$
$echo "(Find out more at https://amber.marbl.cc)"$
echo 'Amber already installed'
echo 'It seems that Amber is already installed on your system. ({place})'
echo 'If you want to reinstall Amber, uninstall it first.'
echo '(Find out more at https://amber.marbl.cc)'
$exit 0$
}

$echo "Installing Amber" $
echo 'Installing Amber'

# Download Amber
if {
# Check if ruby is installed
$ruby -v > /dev/null; echo \$?$ == '0' {
let code = 'require "open-uri"; open("{target}", "wb") do |file|; file << open("{url}").read; end'
$echo "Using ruby as a download method..."$
echo 'Using ruby as a download method...'
$ruby -e "{code}"$
}
# Check if curl is installed
$curl -v > /dev/null; echo \$?$ == '0' {
$echo "Using curl as a download method..."$
echo 'Using curl as a download method...'
$curl -o "{target}" "{url}"$
}
# Check if wget is installed
$wget -v > /dev/null; echo \$?$ == '0' {
$echo "Using wget as a download method..."$
echo 'Using wget as a download method...'
$wget -O "{target}" "{url}"$
}
else {
$echo "Neither ruby, curl or wget are installed on your system."$
$echo "Please install one of them and try again."$
echo 'Neither ruby, curl or wget are installed on your system.'
echo 'Please install one of them and try again.'
$exit 1$
}
}
Expand All @@ -62,4 +62,4 @@ $sudo chmod +x {place}/{target}$
# Create amber symbol link
$sudo ln -s {place}/{target} /usr/local/bin/{target}$
# Send success message
$echo "Amber has been installed successfully. 🎉"$
echo 'Amber has been installed successfully. 🎉'
40 changes: 20 additions & 20 deletions setup/install.sh
Original file line number Diff line number Diff line change
@@ -1,36 +1,36 @@
name="AmberNative";
target="amber";
tag="v0.1.1-alpha";
place="/opt/amber";
os=$(if [ $([ "_$(uname -s)" != "_Darwin" ]; echo $?) != 0 ]; then echo "macos"; else echo "linux"; fi);
arch=$(if [ $([ "_$(uname -m)" != "_arm64" ]; echo $?) != 0 ]; then echo "aarch64"; else echo "x86_64"; fi);
url="https://github.com/Ph0enixKM/${name}/releases/download/${tag}/amber_${os}_${arch}";
test -d "${place}" > /dev/null;
__0_name="AmberNative";
__1_target="amber";
__2_tag="v0.1.1-alpha";
__3_place="/opt/amber";
__4_os=$(if [ $([ "_$(uname -s)" != "_Darwin" ]; echo $?) != 0 ]; then echo "macos"; else echo "linux"; fi);
__5_arch=$(if [ $([ "_$(uname -m)" != "_arm64" ]; echo $?) != 0 ]; then echo "aarch64"; else echo "x86_64"; fi);
__6_url="https://github.com/Ph0enixKM/${__0_name}/releases/download/${__2_tag}/amber_${__4_os}_${__5_arch}";
test -d "${__3_place}" > /dev/null;
if [ $([ "_$(echo $?)" != "_0" ]; echo $?) != 0 ]; then
echo "Amber already installed" ;
echo "It seems that Amber is already installed on your system.";
echo "If you want to reinstall Amber - try to uninstall it first.";
echo "Amber already installed";
echo "It seems that Amber is already installed on your system. (${__3_place})";
echo "If you want to reinstall Amber, uninstall it first.";
echo "(Find out more at https://amber.marbl.cc)";
exit 0
fi;
echo "Installing Amber" ;
echo "Installing Amber";
if [ $([ "_$(ruby -v > /dev/null; echo $?)" != "_0" ]; echo $?) != 0 ]; then
code="require \"open-uri\"; open(\"${target}\", \"wb\") do |file|; file << open(\"${url}\").read; end";
__7_code="require \"open-uri\"; open(\"${__1_target}\", \"wb\") do |file|; file << open(\"${__6_url}\").read; end";
echo "Using ruby as a download method...";
ruby -e "${code}"
ruby -e "${__7_code}"
elif [ $([ "_$(curl -v > /dev/null; echo $?)" != "_0" ]; echo $?) != 0 ]; then
echo "Using curl as a download method...";
curl -o "${target}" "${url}"
curl -o "${__1_target}" "${__6_url}"
elif [ $([ "_$(wget -v > /dev/null; echo $?)" != "_0" ]; echo $?) != 0 ]; then
echo "Using wget as a download method...";
wget -O "${target}" "${url}"
wget -O "${__1_target}" "${__6_url}"
else
echo "Neither ruby, curl or wget are installed on your system.";
echo "Please install one of them and try again.";
exit 1
fi;
sudo mkdir ${place} > /dev/null;
sudo mv ${target} ${place}/${target};
sudo chmod +x ${place}/${target};
sudo ln -s ${place}/${target} /usr/local/bin/${target};
sudo mkdir ${__3_place} > /dev/null;
sudo mv ${__1_target} ${__3_place}/${__1_target};
sudo chmod +x ${__3_place}/${__1_target};
sudo ln -s ${__3_place}/${__1_target} /usr/local/bin/${__1_target};
echo "Amber has been installed successfully. 🎉"
4 changes: 2 additions & 2 deletions setup/uninstall.ab
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ $test -d "{place}" > /dev/null$
if $echo \$?$ == '0' {
$sudo rm -rf "{place}"$
$sudo rm '/usr/local/bin/amber'$
$echo 'Uninstalled Amber successfully 🎉'$
echo 'Uninstalled Amber successfully 🎉'
}
else {
$echo 'Amber is not installed'$
echo 'Amber is not installed'
}
10 changes: 5 additions & 5 deletions setup/uninstall.sh
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
place="/opt/amber";
test -d "${place}" > /dev/null;
__0_place="/opt/amber";
test -d "${__0_place}" > /dev/null;
if [ $([ "_$(echo $?)" != "_0" ]; echo $?) != 0 ]; then
sudo rm -rf "${place}";
sudo rm -rf "${__0_place}";
sudo rm '/usr/local/bin/amber';
echo 'Uninstalled Amber successfully 🎉'
echo "Uninstalled Amber successfully 🎉"
else
echo 'Amber is not installed'
echo "Amber is not installed"
fi
7 changes: 4 additions & 3 deletions src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,13 @@ impl AmberCompiler {

pub fn translate(&self, block: Block, meta: ParserMetadata) -> String {
let imports_sorted = meta.import_history.topological_sort();
let imports_blocks = meta.import_history.import_map.clone();
let imports_blocks = meta.import_history.import_blocks.clone();
let _imports = meta.import_history.imports.clone();
let mut meta = TranslateMetadata::new(&meta);
let mut result = vec![];
for index in imports_sorted.iter() {
if *index != 0 {
result.push(imports_blocks[*index - 1].translate(&mut meta));
if let Some(block) = imports_blocks[*index].clone() {
result.push(block.translate(&mut meta));
}
}
result.push(block.translate(&mut meta));
Expand Down
5 changes: 1 addition & 4 deletions src/modules/function/declaration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,7 @@ impl TranslateModule for FunctionDeclaration {
let blocks = meta.mem.get_function_instances(self.id).unwrap().to_vec();
// Translate each one of them
for (index, function) in blocks.iter().enumerate() {
let mut name = self.name.clone();
if index != 0 {
name = format!("__{}_{}", index, name);
}
let name = format!("__{}_v{}_{}", self.id, index, self.name);
// Parse the function body
result.push(format!("function {} {{", name));
if let Some(args) = self.set_args_as_variables(meta) {
Expand Down
10 changes: 6 additions & 4 deletions src/modules/function/invocation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ pub struct FunctionInvocation {
name: String,
args: Vec<Expr>,
kind: Type,
variant_id: usize
variant_id: usize,
id: usize
}

impl Typed for FunctionInvocation {
Expand All @@ -29,7 +30,8 @@ impl SyntaxModule<ParserMetadata> for FunctionInvocation {
name: String::new(),
args: vec![],
kind: Type::Null,
variant_id: 0
variant_id: 0,
id: 0
}
}

Expand All @@ -39,7 +41,7 @@ impl SyntaxModule<ParserMetadata> for FunctionInvocation {
self.name = variable(meta, variable_name_extensions())?;
// Get the arguments
token(meta, "(")?;
handle_function_reference(meta, tok.clone(), &self.name)?;
self.id = handle_function_reference(meta, tok.clone(), &self.name)?;
loop {
if token(meta, ")").is_ok() {
break
Expand All @@ -60,7 +62,7 @@ impl SyntaxModule<ParserMetadata> for FunctionInvocation {

impl TranslateModule for FunctionInvocation {
fn translate(&self, meta: &mut TranslateMetadata) -> String {
let name = if self.variant_id != 0 { format!("__{}_{}", self.variant_id, self.name) } else { self.name.clone() };
let name = format!("__{}_v{}_{}", self.id, self.variant_id, self.name);
let args = self.args.iter().map(|arg| arg.translate(meta)).collect::<Vec<String>>().join(" ");
format!("$({name} {args})")
}
Expand Down
22 changes: 12 additions & 10 deletions src/modules/function/invocation_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ fn run_function_with_args(meta: &mut ParserMetadata, name: &str, args: &[Type],
// Create a sub context for new variables
new_meta.mem.push_scope();
for (kind, (name, _generic)) in args.iter().zip(function.args.iter()) {
new_meta.mem.add_variable(name, kind.clone());
new_meta.mem.add_variable(name, kind.clone(), false);
}
// Parse the function body
syntax(&mut new_meta, &mut block)?;
Expand All @@ -41,17 +41,19 @@ fn run_function_with_args(meta: &mut ParserMetadata, name: &str, args: &[Type],
Ok(meta.mem.add_function_instance(function.id, args, function.returns, block))
}

pub fn handle_function_reference(meta: &mut ParserMetadata, tok: Option<Token>, name: &str) -> Result<(), Failure> {
if meta.mem.get_function(name).is_none() {
let message = format!("Function '{}' does not exist", name);
// Find other similar variable if exists
return if let Some(comment) = handle_similar_function(meta, name) {
error!(meta, tok, message, comment)
} else {
error!(meta, tok, message)
pub fn handle_function_reference(meta: &mut ParserMetadata, tok: Option<Token>, name: &str) -> Result<usize, Failure> {
match meta.mem.get_function(name) {
Some(fun_decl) => Ok(fun_decl.id),
None => {
let message = format!("Function '{}' does not exist", name);
// Find other similar variable if exists
if let Some(comment) = handle_similar_function(meta, name) {
error!(meta, tok, message, comment)
} else {
error!(meta, tok, message)
}
}
}
Ok(())
}

pub fn handle_function_parameters(meta: &mut ParserMetadata, name: &str, args: &[Type], tok: Option<Token>) -> Result<(Type, usize), Failure> {
Expand Down
40 changes: 17 additions & 23 deletions src/modules/imports/import.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use std::fs;
use std::path::Path;
use heraclitus_compiler::prelude::*;
use crate::compiler::AmberCompiler;
use crate::modules::block::Block;
Expand All @@ -14,7 +13,7 @@ pub struct Import {
}

impl Import {
fn handle_export(&mut self, meta: &mut ParserMetadata, exports: Exports) {
fn handle_export(&mut self, meta: &mut ParserMetadata, exports: Exports) -> SyntaxResult {
for export in exports.get_exports().iter().cloned() {
match export {
ExportUnit::Function(mut func_decl) => {
Expand All @@ -25,6 +24,7 @@ impl Import {
}
}
}
Ok(())
}

fn add_import(&mut self, meta: &mut ParserMetadata, tok: Option<Token>, path: &str) -> SyntaxResult {
Expand All @@ -37,26 +37,8 @@ impl Import {
Ok(())
}

fn resolve_path(&mut self, meta: &mut ParserMetadata, tok: Option<Token>) -> Result<String, Failure> {
let mut path = meta.path.as_ref()
.map_or_else(|| Path::new("."), |path| Path::new(path))
.to_path_buf();
path.pop();
path.push(&self.path.value);
match path.to_str() {
Some(path) => {
self.add_import(meta, tok, path)?;
Ok(path.to_string())
}
None => error!(meta, tok => {
message: format!("Could not resolve path '{}'", path.display()),
comment: "Path is not valid UTF-8"
})
}
}

fn resolve_import(&mut self, meta: &mut ParserMetadata, tok: Option<Token>) -> Result<String, Failure> {
match fs::read_to_string(self.resolve_path(meta, tok.clone())?) {
match fs::read_to_string(self.path.value.clone()) {
Ok(content) => Ok(content),
Err(err) => error!(meta, tok => {
message: format!("Could not read file '{}'", self.path.value),
Expand All @@ -66,6 +48,13 @@ impl Import {
}

fn handle_import(&mut self, meta: &mut ParserMetadata, tok: Option<Token>, imported_code: String) -> SyntaxResult {
match meta.import_history.get_export(Some(self.path.value.clone())) {
Some(exports) => self.handle_export(meta, exports),
None => self.handle_compile_code(meta, tok, imported_code)
}
}

fn handle_compile_code(&mut self, meta: &mut ParserMetadata, tok: Option<Token>, imported_code: String) -> SyntaxResult {
match AmberCompiler::new(imported_code.clone(), Some(self.path.value.clone())).tokenize() {
Ok(tokens) => {
let mut block = Block::new();
Expand All @@ -85,8 +74,9 @@ impl Import {
meta.mem.scopes = vec![];
syntax(meta, &mut block)?;
meta.mem.scopes = scopes;
meta.import_history.import_map.push(block);
self.handle_export(meta, meta.mem.exports.clone());
meta.import_history.add_import_block(Some(self.path.value.clone()), block);
meta.import_history.add_export(Some(self.path.value.clone()), meta.mem.exports.clone());
self.handle_export(meta, meta.mem.exports.clone())?;
// Restore snapshot of current file
meta.code = code;
meta.path = path;
Expand Down Expand Up @@ -115,6 +105,9 @@ impl SyntaxModule<ParserMetadata> for Import {
fn parse(&mut self, meta: &mut ParserMetadata) -> SyntaxResult {
token(meta, "import")?;
let tok = meta.get_current_token();
if meta.mem.get_depth() > 1 {
return error!(meta, tok, "Imports must be in the global scope")
}
token(meta, "*")?;
token(meta, "from")?;
let tok_str = meta.get_current_token();
Expand All @@ -123,6 +116,7 @@ impl SyntaxModule<ParserMetadata> for Import {
self.add_import(meta, tok_str, "[standard library]")?;
AmberCompiler::import_std()
} else {
self.add_import(meta, tok_str.clone(), &self.path.value.clone())?;
self.resolve_import(meta, tok_str)?
};
self.handle_import(meta, tok, imported_code)?;
Expand Down
23 changes: 21 additions & 2 deletions src/modules/imports/import_string.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use heraclitus_compiler::prelude::*;
use std::path::Path;
use crate::utils::ParserMetadata;

#[derive(Debug, Clone)]
Expand All @@ -7,9 +8,26 @@ pub struct ImportString {
}

impl ImportString {
pub fn std_lib_path(&mut self) {
fn resolve_path(&mut self, meta: &mut ParserMetadata, tok: Option<Token>) -> SyntaxResult {
if self.value == "std" {
self.value = "[standard library]".to_string();
return Ok(())

}
let mut path = meta.path.as_ref()
.map_or_else(|| Path::new("."), |path| Path::new(path))
.to_path_buf();
path.pop();
path.push(&self.value);
match path.to_str() {
Some(path) => {
self.value = path.to_string();
Ok(())
}
None => error!(meta, tok => {
message: format!("Could not resolve path '{}'", path.display()),
comment: "Path is not valid UTF-8"
})
}
}
}
Expand All @@ -24,10 +42,11 @@ impl SyntaxModule<ParserMetadata> for ImportString {
}

fn parse(&mut self, meta: &mut ParserMetadata) -> SyntaxResult {
let tok = meta.get_current_token();
let value = token_by(meta, |word| word.starts_with('\''))?;
if value.ends_with('\'') {
self.value = value[1..value.len() - 1].to_string();
self.std_lib_path();
self.resolve_path(meta, tok)?;
}
else {
return error!(meta, meta.get_current_token(), "Import string cannot interpolate expressions")
Expand Down
Loading