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

Move stdlib to different files #291

Merged
merged 26 commits into from
Jul 16, 2024
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
20 changes: 20 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ clap = { version = "4.4.18", features = ["derive"] }
tempfile = "3.10.1"
chrono = "0.4.38"
test-generator = "0.3.1"
include_dir = "0.7.4"

# test dependencies
[dev-dependencies]
Expand Down
7 changes: 5 additions & 2 deletions setup/install.ab
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { has_failed, includes, exit, chars } from "std"
import { has_failed, exit } from "std/env"
import { chars } from "std/text"
import { includes } from "std/array"
import { file_exist } from "std/fs"
import { get_os, get_arch, get_place, get_bins_folder } from "./shared.ab"

let name = "AmberNative"
Expand Down Expand Up @@ -114,7 +117,7 @@ main(args) {

// Delete the previous symbolic link
if file_exist("{bins_folder}/{target}") {
${sudo} rm "{bins_folder}/{target}" failed {
${sudo} rm "{bins_folder}/{target}"$ failed {
echo "Failed to remove the previous amber symbol link."
echo "Please make sure that root user can access {bins_folder} directory."
exit(1)
Expand Down
3 changes: 2 additions & 1 deletion setup/shared.ab
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { exit, includes, has_failed } from "std"
import { has_failed, exit } from "std/env"
import { includes } from "std/array"

pub fun get_os(): Text {
// Determine OS type
Expand Down
3 changes: 0 additions & 3 deletions src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,4 @@ impl AmberCompiler {
})
}

pub fn import_std() -> String {
[include_str!("std/main.ab")].join("\n")
}
}
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ mod modules;
mod rules;
mod translate;
mod utils;
mod stdlib;

#[cfg(test)]
pub mod tests;
Expand Down
30 changes: 17 additions & 13 deletions src/modules/imports/import.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use heraclitus_compiler::prelude::*;
use crate::compiler::AmberCompiler;
use crate::modules::block::Block;
use crate::modules::variable::variable_name_extensions;
use crate::stdlib;
use crate::utils::context::{Context, FunctionDecl};
use crate::utils::{ParserMetadata, TranslateMetadata};
use crate::translate::module::TranslateModule;
Expand Down Expand Up @@ -69,12 +70,20 @@ impl Import {
}

fn resolve_import(&mut self, meta: &ParserMetadata) -> Result<String, Failure> {
match fs::read_to_string(self.path.value.clone()) {
Ok(content) => Ok(content),
Err(err) => error!(meta, self.token_path.clone() => {
message: format!("Could not read file '{}'", self.path.value),
comment: err.to_string()
})
if self.path.value.starts_with("std/") {
match stdlib::resolve(&self.path.value.replace("std/", "")) {
Some(v) => Ok(v),
None => error!(meta, self.token_path.clone(),
format!("Standard library module '{}' does not exist", self.path.value))
}
} else {
match fs::read_to_string(self.path.value.clone()) {
Ok(content) => Ok(content),
Err(err) => error!(meta, self.token_path.clone() => {
message: format!("Could not read file '{}'", self.path.value),
comment: err.to_string()
})
}
}
}

Expand Down Expand Up @@ -157,14 +166,9 @@ impl SyntaxModule<ParserMetadata> for Import {
self.token_path = meta.get_current_token();
syntax(meta, &mut self.path)?;
// Import code from file or standard library
let imported_code = if self.path.value == "[standard library]" {
self.add_import(meta, "[standard library]")?;
AmberCompiler::import_std()
} else {
self.add_import(meta, &self.path.value.clone())?;
self.resolve_import(meta)?
self.add_import(meta, &self.path.value.clone())?;
let imported_code = self.resolve_import(meta)?;

};
self.handle_import(meta, imported_code)?;
Ok(())
}
Expand Down
6 changes: 2 additions & 4 deletions src/modules/imports/import_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,8 @@ pub struct ImportString {

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

}
let mut path = meta.context.path.as_ref()
.map_or_else(|| Path::new("."), |path| Path::new(path))
Expand Down Expand Up @@ -53,4 +51,4 @@ impl SyntaxModule<ParserMetadata> for ImportString {
}
Ok(())
}
}
}
32 changes: 32 additions & 0 deletions src/std/array.ab
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
pub fun array_first_index(array, value): Num {
loop index, element in array {
if value as Text == element as Text {
return index
}
}
return -1
}

pub fun array_search(array, value): [Num] {
let result = [Num]
loop index, element in array {
if value as Text == element as Text {
result += [index]
}
}
return result
}

pub fun in_array(array, value): Bool {
let result = array_first_index(array, value)
return result >= 0
}

pub fun includes(arr, value) {
loop v in arr {
if v == value {
return true
}
}
return false
}
76 changes: 76 additions & 0 deletions src/std/env.ab
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import * from "std/fs"

pub fun get_env_var(var: Text): Text {
let _var = unsafe $echo "\$\{!var}"$
if _var != "" {
return _var
}

if file_exist(".env") {
unsafe $source ".env"$
return unsafe $echo "\$\{!var}"$
}

return ""
}

pub fun load_env_file(): Null {
unsafe $export "\$(xargs < .env)" > /dev/null$
}

pub fun shell_isset(name: Text): Bool {
$[[ ! -z \$\{!{nameof name}+z} ]]$ failed {
return false
}
return true
}

pub fun shell_constant_set(name: Text, val: Text): Null {
$readonly \${nameof name}="\${nameof val}" 2> /dev/null$?
}

pub fun shell_constant_get(name: Text): Text {
return $echo \$\{!{nameof name}}$?
}

pub fun shell_var_set(name: Text, val: Text): Null {
$export \${nameof name}="\${nameof val}" 2> /dev/null$?
}

pub fun shell_var_get(name: Text): Text {
return $echo \$\{!{nameof name}}$?
}

pub fun shell_unset(name: Text): Null {
$unset {name}$?
}

pub fun is_command(command: Text): Bool {
$[ -x "\$(command -v {command})" ]$ failed {
return false
}
return true
}

pub fun input(prompt: Text): Text {
unsafe $printf "\${nameof prompt}"$
unsafe $read$
return "\$REPLY"
}

pub fun has_failed(command: Text): Bool {
unsafe silent $eval {command}$
return status != 0
}

pub fun exit(code: Num): Null {
unsafe $exit "{code}"$
}

pub fun is_root(): Bool {
if unsafe $id -u$ == "0" {
return true
}

return false
}
60 changes: 60 additions & 0 deletions src/std/fs.ab
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
pub fun dir_exist(path) {
$[ -d "{path}" ]$ failed {
return false
}
return true
}

pub fun file_exist(path) {
$[ -f "{path}" ]$ failed {
return false
}
return true
}

pub fun file_read(path) {
return $< "{path}"$?
}

pub fun file_write(path, content) {
return $echo "{content}" > "{path}"$?
}

pub fun file_append(path, content) {
return $echo "{content}" >> "{path}"$?
}

pub fun create_symbolic_link(origin: Text, destination: Text): Bool {
if file_exist(origin) {
unsafe $ln -s "{origin}" "{destination}"$
return true
}

echo "The file {origin} doesn't exist!"
return false
}

pub fun create_dir(path: Text): Null {
if not dir_exist(path) {
unsafe $mkdir -p "{path}"$
}
}

pub fun make_executable(path: Text): Bool {
if file_exist(path) {
unsafe $chmod +x "{path}"$
return true
}

echo "The file {path} doesn't exist!"
return false
}

pub fun change_owner(user: Text, path: Text): Bool {
if file_exist(path) or dir_exist(path) {
unsafe $chown -R "{user}" "{path}"$
return true
}

return false
}
20 changes: 20 additions & 0 deletions src/std/http.ab
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import * from "std/env"

pub fun download(url: Text, path: Text): Bool {
if {
is_command("curl") {
unsafe $curl -L -o "{path}" "{url}"$
}
is_command("wget") {
unsafe $wget "{url}" -P "{path}"$
}
is_command("aria2c") {
unsafe $aria2c "{url}" -d "{path}"$
}
else {
return false
}
}

return true
}
Loading
Loading