mirror of
https://github.com/edg-l/edlang.git
synced 2024-11-09 09:38:24 +00:00
Compare commits
5 commits
22498719e1
...
edb872a218
Author | SHA1 | Date | |
---|---|---|---|
Edgar | edb872a218 | ||
Edgar | 2e5d9ae618 | ||
Edgar | d2ee70c767 | ||
Edgar | d56fe11b0c | ||
Edgar | bd3c4da7ea |
3
.github/workflows/release.yml
vendored
3
.github/workflows/release.yml
vendored
|
@ -53,4 +53,5 @@ jobs:
|
|||
README.md
|
||||
LICENSE
|
||||
CHANGES.md
|
||||
target/release/edlang
|
||||
target/release/edlangc
|
||||
target/release/edb
|
||||
|
|
19
CHANGELOG.md
19
CHANGELOG.md
|
@ -2,6 +2,21 @@
|
|||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## [unreleased]
|
||||
|
||||
### 🚀 Features
|
||||
|
||||
- More checks
|
||||
- More checks
|
||||
- Initial work on edb, the edlang project manager
|
||||
- Usable edb
|
||||
- Version and readme
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
||||
- Fix span in lalrpop
|
||||
- Fix on type qualifier lowering
|
||||
|
||||
## [0.0.1-alpha.12] - 2024-03-02
|
||||
|
||||
### 🚀 Features
|
||||
|
@ -16,6 +31,10 @@ All notable changes to this project will be documented in this file.
|
|||
|
||||
- Add cast test
|
||||
|
||||
### ⚙️ Miscellaneous Tasks
|
||||
|
||||
- Version 0.0.1-alpha.12
|
||||
|
||||
## [0.0.1-alpha.11] - 2024-03-01
|
||||
|
||||
### 🚀 Features
|
||||
|
|
30
Cargo.lock
generated
30
Cargo.lock
generated
|
@ -235,26 +235,27 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "edb"
|
||||
version = "0.0.1-alpha.12"
|
||||
version = "0.0.1-alpha.14"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
"edlang_driver",
|
||||
"git2",
|
||||
"owo-colors",
|
||||
"serde",
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "edlang_ast"
|
||||
version = "0.0.1-alpha.12"
|
||||
version = "0.0.1-alpha.14"
|
||||
dependencies = [
|
||||
"edlang_span",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "edlang_check"
|
||||
version = "0.0.1-alpha.12"
|
||||
version = "0.0.1-alpha.14"
|
||||
dependencies = [
|
||||
"ariadne",
|
||||
"edlang_ast",
|
||||
|
@ -265,7 +266,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "edlang_codegen_llvm"
|
||||
version = "0.0.1-alpha.12"
|
||||
version = "0.0.1-alpha.14"
|
||||
dependencies = [
|
||||
"edlang_ir",
|
||||
"edlang_parser",
|
||||
|
@ -278,7 +279,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "edlang_driver"
|
||||
version = "0.0.1-alpha.12"
|
||||
version = "0.0.1-alpha.14"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"ariadne",
|
||||
|
@ -294,11 +295,12 @@ dependencies = [
|
|||
"test-case",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "edlang_ir"
|
||||
version = "0.0.1-alpha.12"
|
||||
version = "0.0.1-alpha.14"
|
||||
dependencies = [
|
||||
"edlang_span",
|
||||
"educe",
|
||||
|
@ -307,7 +309,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "edlang_lowering"
|
||||
version = "0.0.1-alpha.12"
|
||||
version = "0.0.1-alpha.14"
|
||||
dependencies = [
|
||||
"edlang_ast",
|
||||
"edlang_ir",
|
||||
|
@ -317,7 +319,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "edlang_parser"
|
||||
version = "0.0.1-alpha.12"
|
||||
version = "0.0.1-alpha.14"
|
||||
dependencies = [
|
||||
"ariadne",
|
||||
"edlang_ast",
|
||||
|
@ -330,18 +332,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "edlang_session"
|
||||
version = "0.0.1-alpha.12"
|
||||
version = "0.0.1-alpha.14"
|
||||
dependencies = [
|
||||
"ariadne",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "edlang_span"
|
||||
version = "0.0.1-alpha.12"
|
||||
version = "0.0.1-alpha.14"
|
||||
|
||||
[[package]]
|
||||
name = "edlangc"
|
||||
version = "0.0.1-alpha.12"
|
||||
version = "0.0.1-alpha.14"
|
||||
dependencies = [
|
||||
"edlang_driver",
|
||||
]
|
||||
|
@ -785,6 +787,12 @@ version = "0.1.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
|
||||
|
||||
[[package]]
|
||||
name = "owo-colors"
|
||||
version = "4.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "caff54706df99d2a78a5a4e3455ff45448d81ef1bb63c22cd14052ca0e993a3f"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.12.1"
|
||||
|
|
19
README.md
19
README.md
|
@ -21,6 +21,25 @@ mod Main {
|
|||
}
|
||||
```
|
||||
|
||||
## edb: The edlang builder
|
||||
|
||||
`edb` is a tool like cargo but for edlang:
|
||||
|
||||
```
|
||||
edlang builder
|
||||
|
||||
Usage: edlang <COMMAND>
|
||||
|
||||
Commands:
|
||||
new Initialize a project
|
||||
build Build a project
|
||||
help Print this message or the help of the given subcommand(s)
|
||||
|
||||
Options:
|
||||
-h, --help Print help
|
||||
-V, --version Print version
|
||||
```
|
||||
|
||||
## Dependencies
|
||||
|
||||
- Rust
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "edlangc"
|
||||
version = "0.0.1-alpha.12"
|
||||
version = "0.0.1-alpha.14"
|
||||
authors = ["Edgar Luque <edgar@edgarluque.com>"]
|
||||
description = "A experimental language using LLVM."
|
||||
edition = "2021"
|
||||
|
@ -14,4 +14,4 @@ repository = "https://github.com/edg-l/edlang"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
edlang_driver = { version = "0.0.1-alpha.12", path = "../../lib/edlang_driver" }
|
||||
edlang_driver = { version = "0.0.1-alpha.14", path = "../../lib/edlang_driver" }
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "edb"
|
||||
version = "0.0.1-alpha.12"
|
||||
version = "0.0.1-alpha.14"
|
||||
authors = ["Edgar Luque <edgar@edgarluque.com>"]
|
||||
description = "The edlang language builder."
|
||||
edition = "2021"
|
||||
|
@ -14,9 +14,10 @@ repository = "https://github.com/edg-l/edlang"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
edlang_driver = { version = "0.0.1-alpha.12", path = "../lib/edlang_driver" }
|
||||
edlang_driver = { version = "0.0.1-alpha.14", path = "../lib/edlang_driver" }
|
||||
anyhow = "1"
|
||||
clap = { version = "4.4.16", features = ["derive"] }
|
||||
toml = "0.8.10"
|
||||
serde = { version = "1.0.197", features = ["derive"] }
|
||||
git2 = "0.18.2"
|
||||
owo-colors = "4.0.0"
|
||||
|
|
154
edb/src/main.rs
154
edb/src/main.rs
|
@ -1,9 +1,15 @@
|
|||
use std::{collections::HashMap, path::PathBuf};
|
||||
use std::{collections::HashMap, fs::File, io::Read, path::PathBuf, time::Instant};
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use anyhow::{bail, Context, Result};
|
||||
use clap::{Parser, Subcommand};
|
||||
use config::{Config, Package, Profile};
|
||||
use git2::{IndexAddOption, Repository, RepositoryInitOptions};
|
||||
use edlang_driver::{
|
||||
compile,
|
||||
linker::{link_binary, link_shared_lib},
|
||||
CompilerArgs,
|
||||
};
|
||||
use git2::{IndexAddOption, Repository};
|
||||
use owo_colors::OwoColorize;
|
||||
|
||||
mod config;
|
||||
|
||||
|
@ -36,6 +42,10 @@ enum Commands {
|
|||
/// Build for release with all optimizations.
|
||||
#[arg(short, long, default_value_t = false)]
|
||||
release: bool,
|
||||
|
||||
/// Override the profile to use.
|
||||
#[arg(short, long)]
|
||||
profile: Option<String>,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -131,13 +141,13 @@ mod {} {{
|
|||
}
|
||||
|
||||
{
|
||||
let mut repo = Repository::init(&path).context("failed to create repository")?;
|
||||
let repo = Repository::init(&path).context("failed to create repository")?;
|
||||
let sig = repo.signature()?;
|
||||
let tree_id = {
|
||||
let mut index = repo.index()?;
|
||||
|
||||
index.add_all(["*"], IndexAddOption::DEFAULT, None)?;
|
||||
|
||||
index.add_all(["."].iter(), IndexAddOption::DEFAULT, None)?;
|
||||
index.write()?;
|
||||
index.write_tree()?
|
||||
};
|
||||
|
||||
|
@ -145,8 +155,138 @@ mod {} {{
|
|||
repo.commit(Some("HEAD"), &sig, &sig, "Initial commit", &tree, &[])
|
||||
.context("failed to create initial commit")?;
|
||||
}
|
||||
|
||||
if bin {
|
||||
println!(
|
||||
" {} binary (application) `{}` package",
|
||||
"Created".green().bold(),
|
||||
name
|
||||
);
|
||||
} else {
|
||||
println!(" {} library `{}` package", "Created".green(), name);
|
||||
}
|
||||
}
|
||||
Commands::Build { release, profile } => {
|
||||
let mut current_dir = std::env::current_dir()?;
|
||||
let mut config_path = None;
|
||||
|
||||
for _ in 0..3 {
|
||||
if !current_dir.join("Ed.toml").exists() {
|
||||
current_dir = if let Some(parent) = current_dir.parent() {
|
||||
parent.to_path_buf()
|
||||
} else {
|
||||
bail!("Couldn't find Ed.toml");
|
||||
};
|
||||
} else {
|
||||
config_path = Some(current_dir.join("Ed.toml"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let config_path = match config_path {
|
||||
Some(x) => x,
|
||||
None => bail!("Couldn't find Ed.toml"),
|
||||
};
|
||||
|
||||
let base_dir = config_path
|
||||
.parent()
|
||||
.context("couldn't get config parent dir")?;
|
||||
let mut config = File::open(&config_path).context("Failed to open Ed.toml")?;
|
||||
let mut buf = String::new();
|
||||
config.read_to_string(&mut buf)?;
|
||||
|
||||
let config: Config = toml::from_str(&buf).context("failed to parse Ed.toml")?;
|
||||
|
||||
println!(
|
||||
" {} {} v{} ({})",
|
||||
"Compiling".green().bold(),
|
||||
config.package.name,
|
||||
config.package.version,
|
||||
base_dir.display()
|
||||
);
|
||||
|
||||
let src_dir = base_dir.join("src");
|
||||
let target_dir = base_dir.join("target-ed");
|
||||
|
||||
if !target_dir.exists() {
|
||||
std::fs::create_dir_all(&target_dir)?;
|
||||
}
|
||||
|
||||
let has_main = src_dir.join("main.ed").exists();
|
||||
let output = target_dir.join(config.package.name);
|
||||
|
||||
let (profile, profile_name) = if let Some(profile) = profile {
|
||||
(
|
||||
config
|
||||
.profile
|
||||
.get(&profile)
|
||||
.context("Couldn't get requested profile")?,
|
||||
profile,
|
||||
)
|
||||
} else if release {
|
||||
(
|
||||
config
|
||||
.profile
|
||||
.get("release")
|
||||
.context("Couldn't get profile: release")?,
|
||||
"release".to_string(),
|
||||
)
|
||||
} else {
|
||||
(
|
||||
config
|
||||
.profile
|
||||
.get("dev")
|
||||
.context("Couldn't get profile: dev")?,
|
||||
"dev".to_string(),
|
||||
)
|
||||
};
|
||||
|
||||
let compile_args = CompilerArgs {
|
||||
input: src_dir,
|
||||
output: output.clone(),
|
||||
release,
|
||||
optlevel: Some(profile.opt_level),
|
||||
debug_info: Some(profile.debug_info),
|
||||
library: !has_main,
|
||||
ast: false,
|
||||
ir: false,
|
||||
llvm: true,
|
||||
asm: false,
|
||||
object: true,
|
||||
};
|
||||
|
||||
let start = Instant::now();
|
||||
let object = compile(&compile_args)?;
|
||||
|
||||
if !has_main {
|
||||
link_shared_lib(&[object], &output)?;
|
||||
} else {
|
||||
link_binary(&[object], &output)?;
|
||||
}
|
||||
|
||||
let elapsed = start.elapsed();
|
||||
|
||||
println!(
|
||||
" {} {} [{}{}] in {elapsed:?}",
|
||||
"Finished".green().bold(),
|
||||
profile_name,
|
||||
if profile.opt_level > 0 {
|
||||
"optimized"
|
||||
} else {
|
||||
"unoptimized"
|
||||
},
|
||||
if profile.debug_info {
|
||||
" + debuginfo"
|
||||
} else {
|
||||
""
|
||||
}
|
||||
);
|
||||
/*
|
||||
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 0.06s
|
||||
Running `/data2/edgar/edlang/target/debug/edb build`
|
||||
*/
|
||||
}
|
||||
Commands::Build { release } => todo!(),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "edlang_ast"
|
||||
version = "0.0.1-alpha.12"
|
||||
version = "0.0.1-alpha.14"
|
||||
authors = ["Edgar Luque <edgar@edgarluque.com>"]
|
||||
description = "edlang AST"
|
||||
edition = "2021"
|
||||
|
@ -13,4 +13,4 @@ repository = "https://github.com/edg-l/edlang"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
edlang_span = { version = "0.0.1-alpha.12", path = "../edlang_span" }
|
||||
edlang_span = { version = "0.0.1-alpha.14", path = "../edlang_span" }
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "edlang_check"
|
||||
version = "0.0.1-alpha.12"
|
||||
version = "0.0.1-alpha.14"
|
||||
authors = ["Edgar Luque <edgar@edgarluque.com>"]
|
||||
description = "edlang check"
|
||||
edition = "2021"
|
||||
|
@ -14,7 +14,7 @@ repository = "https://github.com/edg-l/edlang"
|
|||
|
||||
[dependencies]
|
||||
ariadne = { version = "0.4.0", features = ["auto-color"] }
|
||||
edlang_ast = { version = "0.0.1-alpha.12", path = "../edlang_ast" }
|
||||
edlang_lowering = { version = "0.0.1-alpha.12", path = "../edlang_lowering" }
|
||||
edlang_session = { version = "0.0.1-alpha.12", path = "../edlang_session" }
|
||||
edlang_ast = { version = "0.0.1-alpha.14", path = "../edlang_ast" }
|
||||
edlang_lowering = { version = "0.0.1-alpha.14", path = "../edlang_lowering" }
|
||||
edlang_session = { version = "0.0.1-alpha.14", path = "../edlang_session" }
|
||||
tracing = { workspace = true }
|
||||
|
|
|
@ -9,11 +9,15 @@ pub fn lowering_error_to_report(
|
|||
error: LoweringError,
|
||||
session: &Session,
|
||||
) -> Report<(String, Range<usize>)> {
|
||||
let path = session.file_path.display().to_string();
|
||||
let mut colors = ColorGenerator::new();
|
||||
colors.next();
|
||||
match error {
|
||||
LoweringError::ModuleNotFound { span, module } => {
|
||||
LoweringError::ModuleNotFound {
|
||||
span,
|
||||
module,
|
||||
file_id,
|
||||
} => {
|
||||
let path = session.file_paths[file_id].display().to_string();
|
||||
let offset = span.lo;
|
||||
Report::build(ReportKind::Error, path.clone(), offset)
|
||||
.with_code("E1")
|
||||
|
@ -25,55 +29,79 @@ pub fn lowering_error_to_report(
|
|||
.with_message("Unresolved import.")
|
||||
.finish()
|
||||
}
|
||||
LoweringError::FunctionNotFound { span, function } => {
|
||||
LoweringError::FunctionNotFound {
|
||||
span,
|
||||
function,
|
||||
file_id,
|
||||
} => {
|
||||
let path = session.file_paths[file_id].display().to_string();
|
||||
Report::build(ReportKind::Error, path.clone(), span.lo)
|
||||
.with_code("EFNNOTFOUND")
|
||||
.with_label(
|
||||
Label::new((path, span.into()))
|
||||
.with_message(format!("Function {function:?} not found."))
|
||||
.with_color(colors.next()),
|
||||
)
|
||||
.finish()
|
||||
},
|
||||
LoweringError::ImportNotFound { import_span, module_span, symbol } => {
|
||||
let offset = symbol.span.lo;
|
||||
Report::build(ReportKind::Error, path.clone(), offset)
|
||||
.with_code("E2")
|
||||
.with_label(
|
||||
Label::new((path.clone(), module_span.into()))
|
||||
.with_message("In module this module."),
|
||||
)
|
||||
.with_label(
|
||||
Label::new((path.clone(), import_span.into()))
|
||||
.with_message("In this import statement"),
|
||||
)
|
||||
.with_label(
|
||||
Label::new((path, symbol.span.into()))
|
||||
.with_message(format!("Failed to find symbol {:?}", symbol.name))
|
||||
.with_color(colors.next()),
|
||||
)
|
||||
.with_message("Unresolved import.")
|
||||
.finish()
|
||||
},
|
||||
LoweringError::BorrowNotMutable { span, name, type_span } => {
|
||||
let mut labels = vec![
|
||||
Label::new((path.clone(), span.into()))
|
||||
.with_message(format!("Can't mutate {name:?} because it's behind a immutable borrow"))
|
||||
.with_color(colors.next())
|
||||
];
|
||||
.with_code("EFNNOTFOUND")
|
||||
.with_label(
|
||||
Label::new((path, span.into()))
|
||||
.with_message(format!("Function {function:?} not found."))
|
||||
.with_color(colors.next()),
|
||||
)
|
||||
.finish()
|
||||
}
|
||||
LoweringError::ImportNotFound {
|
||||
import_span,
|
||||
module_span,
|
||||
symbol,
|
||||
file_id,
|
||||
} => {
|
||||
let path = session.file_paths[file_id].display().to_string();
|
||||
let offset = symbol.span.lo;
|
||||
Report::build(ReportKind::Error, path.clone(), offset)
|
||||
.with_code("E2")
|
||||
.with_label(
|
||||
Label::new((path.clone(), module_span.into()))
|
||||
.with_message("In module this module."),
|
||||
)
|
||||
.with_label(
|
||||
Label::new((path.clone(), import_span.into()))
|
||||
.with_message("In this import statement"),
|
||||
)
|
||||
.with_label(
|
||||
Label::new((path, symbol.span.into()))
|
||||
.with_message(format!("Failed to find symbol {:?}", symbol.name))
|
||||
.with_color(colors.next()),
|
||||
)
|
||||
.with_message("Unresolved import.")
|
||||
.finish()
|
||||
}
|
||||
LoweringError::BorrowNotMutable {
|
||||
span,
|
||||
name,
|
||||
type_span,
|
||||
file_id,
|
||||
} => {
|
||||
let path = session.file_paths[file_id].display().to_string();
|
||||
let mut labels = vec![Label::new((path.clone(), span.into()))
|
||||
.with_message(format!(
|
||||
"Can't mutate {name:?} because it's behind a immutable borrow"
|
||||
))
|
||||
.with_color(colors.next())];
|
||||
|
||||
if let Some(type_span) = type_span {
|
||||
labels.push(Label::new((path.clone(), type_span.into()))
|
||||
.with_message(format!("Variable {name:?} has this type"))
|
||||
.with_color(colors.next()));
|
||||
labels.push(
|
||||
Label::new((path.clone(), type_span.into()))
|
||||
.with_message(format!("Variable {name:?} has this type"))
|
||||
.with_color(colors.next()),
|
||||
);
|
||||
}
|
||||
|
||||
Report::build(ReportKind::Error, path.clone(), span.lo)
|
||||
.with_code("EREFMUT")
|
||||
.with_labels(labels)
|
||||
.finish()
|
||||
},
|
||||
LoweringError::UnrecognizedType { span, name } => {
|
||||
.with_code("EREFMUT")
|
||||
.with_labels(labels)
|
||||
.finish()
|
||||
}
|
||||
LoweringError::UnrecognizedType {
|
||||
span,
|
||||
name,
|
||||
file_id,
|
||||
} => {
|
||||
let path = session.file_paths[file_id].display().to_string();
|
||||
Report::build(ReportKind::Error, path.clone(), span.lo)
|
||||
.with_code("E3")
|
||||
.with_label(
|
||||
|
@ -83,19 +111,26 @@ pub fn lowering_error_to_report(
|
|||
)
|
||||
.with_message(format!("Unresolved type {:?}.", name))
|
||||
.finish()
|
||||
},
|
||||
LoweringError::UnexpectedType { span, found, expected } => {
|
||||
let mut labels = vec![
|
||||
Label::new((path.clone(), span.into()))
|
||||
.with_message(format!("Unexpected type '{}', expected '{}'", found, expected.kind))
|
||||
.with_color(colors.next())
|
||||
];
|
||||
}
|
||||
LoweringError::UnexpectedType {
|
||||
span,
|
||||
found,
|
||||
expected,
|
||||
file_id,
|
||||
} => {
|
||||
let path = session.file_paths[file_id].display().to_string();
|
||||
let mut labels = vec![Label::new((path.clone(), span.into()))
|
||||
.with_message(format!(
|
||||
"Unexpected type '{}', expected '{}'",
|
||||
found, expected.kind
|
||||
))
|
||||
.with_color(colors.next())];
|
||||
|
||||
if let Some(span) = expected.span {
|
||||
labels.push(
|
||||
Label::new((path.clone(), span.into()))
|
||||
.with_message(format!("expected '{}' due to this type", expected.kind))
|
||||
.with_color(colors.next())
|
||||
.with_color(colors.next()),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -104,8 +139,9 @@ pub fn lowering_error_to_report(
|
|||
.with_labels(labels)
|
||||
.with_message(format!("expected type {}.", expected.kind))
|
||||
.finish()
|
||||
},
|
||||
LoweringError::IdNotFound { span, id } => {
|
||||
}
|
||||
LoweringError::IdNotFound { span, id, file_id } => {
|
||||
let path = session.file_paths[file_id].display().to_string();
|
||||
Report::build(ReportKind::Error, path.clone(), span.lo)
|
||||
.with_code("E_ID")
|
||||
.with_label(
|
||||
|
@ -115,8 +151,13 @@ pub fn lowering_error_to_report(
|
|||
)
|
||||
.with_message(format!("Failed to find definition id {id:?}, this is most likely a compiler bug or a unimplemented lowering"))
|
||||
.finish()
|
||||
},
|
||||
LoweringError::NotYetImplemented { span, message } => {
|
||||
}
|
||||
LoweringError::NotYetImplemented {
|
||||
span,
|
||||
message,
|
||||
file_id,
|
||||
} => {
|
||||
let path = session.file_paths[file_id].display().to_string();
|
||||
Report::build(ReportKind::Error, path.clone(), span.lo)
|
||||
.with_code("TODO")
|
||||
.with_label(
|
||||
|
@ -125,16 +166,21 @@ pub fn lowering_error_to_report(
|
|||
.with_color(colors.next()),
|
||||
)
|
||||
.finish()
|
||||
},
|
||||
LoweringError::UseOfUndeclaredVariable { span, name } => {
|
||||
}
|
||||
LoweringError::UseOfUndeclaredVariable {
|
||||
span,
|
||||
name,
|
||||
file_id,
|
||||
} => {
|
||||
let path = session.file_paths[file_id].display().to_string();
|
||||
Report::build(ReportKind::Error, path.clone(), span.lo)
|
||||
.with_code("UseOfUndeclaredVariable")
|
||||
.with_label(
|
||||
Label::new((path, span.into()))
|
||||
.with_message(format!("use of undeclared variable {:?}", name))
|
||||
.with_color(colors.next()),
|
||||
)
|
||||
.finish()
|
||||
},
|
||||
.with_code("UseOfUndeclaredVariable")
|
||||
.with_label(
|
||||
Label::new((path, span.into()))
|
||||
.with_message(format!("use of undeclared variable {:?}", name))
|
||||
.with_color(colors.next()),
|
||||
)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "edlang_codegen_llvm"
|
||||
version = "0.0.1-alpha.12"
|
||||
version = "0.0.1-alpha.14"
|
||||
authors = ["Edgar Luque <edgar@edgarluque.com>"]
|
||||
description = "edlang LLVM codegen"
|
||||
edition = "2021"
|
||||
|
@ -13,10 +13,10 @@ repository = "https://github.com/edg-l/edlang"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
edlang_ir = { version = "0.0.1-alpha.12", path = "../edlang_ir" }
|
||||
edlang_parser = { version = "0.0.1-alpha.12", path = "../edlang_parser" }
|
||||
edlang_session = { version = "0.0.1-alpha.12", path = "../edlang_session" }
|
||||
edlang_ir = { version = "0.0.1-alpha.14", path = "../edlang_ir" }
|
||||
edlang_parser = { version = "0.0.1-alpha.14", path = "../edlang_parser" }
|
||||
edlang_session = { version = "0.0.1-alpha.14", path = "../edlang_session" }
|
||||
llvm-sys = "170.0.1"
|
||||
inkwell = { git = "https://github.com/TheDan64/inkwell", rev = "e0aa2e51a6cb501e4e2a889bbea12a1efab9c4ff", features = ["llvm17-0"] }
|
||||
tracing = { workspace = true }
|
||||
edlang_span = { version = "0.0.1-alpha.12", path = "../edlang_span" }
|
||||
edlang_span = { version = "0.0.1-alpha.14", path = "../edlang_span" }
|
||||
|
|
|
@ -35,17 +35,19 @@ struct ModuleCompileCtx<'ctx, 'm> {
|
|||
di_builder: DebugInfoBuilder<'ctx>,
|
||||
di_unit: DICompileUnit<'ctx>,
|
||||
target_data: TargetData,
|
||||
_module_id: DefId,
|
||||
module_id: DefId,
|
||||
di_namespace: DIScope<'ctx>,
|
||||
}
|
||||
|
||||
impl<'ctx, 'm> ModuleCompileCtx<'ctx, 'm> {
|
||||
pub fn _get_module_body(&self) -> &ModuleBody {
|
||||
self.ctx.program.modules.get(&self._module_id).unwrap()
|
||||
pub fn get_module_body(&self) -> &ModuleBody {
|
||||
self.ctx.program.modules.get(&self.module_id).unwrap()
|
||||
}
|
||||
|
||||
pub fn set_debug_loc(&self, scope: DIScope<'ctx>, span: Span) -> DILocation<'ctx> {
|
||||
let (_, line, column) = self.ctx.session.source.get_offset_line(span.lo).unwrap();
|
||||
let (_, line, column) = self.ctx.session.sources[self.get_module_body().file_id]
|
||||
.get_offset_line(span.lo)
|
||||
.unwrap();
|
||||
let debug_loc = self.di_builder.create_debug_location(
|
||||
self.ctx.context,
|
||||
line as u32 + 1,
|
||||
|
@ -98,25 +100,39 @@ pub fn compile(session: &Session, program: &ProgramBody) -> Result<PathBuf, Box<
|
|||
|
||||
info!("compiling for: {:?}", target.get_description());
|
||||
|
||||
let filename = session.file_path.file_name().unwrap().to_string_lossy();
|
||||
let dir = session.file_path.parent().unwrap().to_string_lossy();
|
||||
for module_id in program.top_level_modules.iter() {
|
||||
let module = ctx.program.modules.get(module_id).unwrap();
|
||||
let file_path = session.file_paths[module.file_id].clone();
|
||||
let abs_file_path = file_path
|
||||
.canonicalize()
|
||||
.expect("failed to canonicalize file path");
|
||||
let filename = file_path.file_name().unwrap().to_str().unwrap();
|
||||
let dirname = abs_file_path
|
||||
.parent()
|
||||
.unwrap()
|
||||
.file_name()
|
||||
.unwrap()
|
||||
.to_str()
|
||||
.unwrap();
|
||||
|
||||
let llvm_module = context.create_module(&module.name);
|
||||
llvm_module.set_source_file_name(&filename);
|
||||
llvm_module.set_source_file_name(filename);
|
||||
llvm_module.set_triple(&triple);
|
||||
llvm_module.set_data_layout(&machine.get_target_data().get_data_layout());
|
||||
let (di_builder, di_unit) = llvm_module.create_debug_info_builder(
|
||||
true,
|
||||
inkwell::debug_info::DWARFSourceLanguage::Rust,
|
||||
&filename,
|
||||
&dir,
|
||||
filename,
|
||||
dirname,
|
||||
"edlang",
|
||||
true,
|
||||
"", // compiler flags
|
||||
1,
|
||||
"", // split name
|
||||
inkwell::debug_info::DWARFEmissionKind::Full,
|
||||
match session.debug_info {
|
||||
edlang_session::DebugInfo::None => inkwell::debug_info::DWARFEmissionKind::None,
|
||||
edlang_session::DebugInfo::Full => inkwell::debug_info::DWARFEmissionKind::Full,
|
||||
},
|
||||
module.module_id.program_id.try_into().unwrap(), // compile unit id?
|
||||
false,
|
||||
false,
|
||||
|
@ -135,7 +151,7 @@ pub fn compile(session: &Session, program: &ProgramBody) -> Result<PathBuf, Box<
|
|||
di_unit,
|
||||
builder: &builder,
|
||||
target_data: machine.get_target_data(),
|
||||
_module_id: *module_id,
|
||||
module_id: *module_id,
|
||||
di_namespace,
|
||||
};
|
||||
|
||||
|
@ -234,10 +250,7 @@ fn compile_fn_signature(ctx: &ModuleCompileCtx<'_, '_>, fn_id: DefId) {
|
|||
|
||||
fn_value.set_call_conventions(0); // cconv
|
||||
|
||||
let (_, line, _col) = ctx
|
||||
.ctx
|
||||
.session
|
||||
.source
|
||||
let (_, line, _col) = ctx.ctx.session.sources[ctx.get_module_body().file_id]
|
||||
.get_offset_line(body.fn_span.lo)
|
||||
.unwrap();
|
||||
|
||||
|
@ -1480,10 +1493,7 @@ fn compile_debug_type<'ctx>(ctx: &ModuleCompileCtx<'ctx, '_>, ty: &ir::TypeInfo)
|
|||
fields.push(ty);
|
||||
}
|
||||
|
||||
let (_, line, _column) = ctx
|
||||
.ctx
|
||||
.session
|
||||
.source
|
||||
let (_, line, _column) = ctx.ctx.session.sources[ctx.get_module_body().file_id]
|
||||
.get_offset_line(body.span.lo)
|
||||
.unwrap();
|
||||
let real_ty = compile_basic_type(ctx, ty);
|
||||
|
|
|
@ -7,7 +7,6 @@ use edlang_session::Session;
|
|||
use ir::ProgramBody;
|
||||
|
||||
pub mod codegen;
|
||||
pub mod linker;
|
||||
|
||||
pub fn compile(
|
||||
session: &Session,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "edlang_driver"
|
||||
version = "0.0.1-alpha.12"
|
||||
version = "0.0.1-alpha.14"
|
||||
authors = ["Edgar Luque <edgar@edgarluque.com>"]
|
||||
description = "edlang compiler driver library"
|
||||
edition = "2021"
|
||||
|
@ -16,15 +16,16 @@ repository = "https://github.com/edg-l/edlang"
|
|||
ariadne = { version = "0.4.0", features = ["auto-color"] }
|
||||
clap = { version = "4.4.16", features = ["derive"] }
|
||||
anyhow = "1"
|
||||
edlang_ast = { version = "0.0.1-alpha.12", path = "../edlang_ast" }
|
||||
edlang_check = { version = "0.0.1-alpha.12", path = "../edlang_check" }
|
||||
edlang_codegen_llvm = { version = "0.0.1-alpha.12", path = "../edlang_codegen_llvm" }
|
||||
edlang_ir = { version = "0.0.1-alpha.12", path = "../edlang_ir" }
|
||||
edlang_lowering = { version = "0.0.1-alpha.12", path = "../edlang_lowering" }
|
||||
edlang_parser = { version = "0.0.1-alpha.12", path = "../edlang_parser" }
|
||||
edlang_session = { version = "0.0.1-alpha.12", path = "../edlang_session" }
|
||||
edlang_ast = { version = "0.0.1-alpha.14", path = "../edlang_ast" }
|
||||
edlang_check = { version = "0.0.1-alpha.14", path = "../edlang_check" }
|
||||
edlang_codegen_llvm = { version = "0.0.1-alpha.14", path = "../edlang_codegen_llvm" }
|
||||
edlang_ir = { version = "0.0.1-alpha.14", path = "../edlang_ir" }
|
||||
edlang_lowering = { version = "0.0.1-alpha.14", path = "../edlang_lowering" }
|
||||
edlang_parser = { version = "0.0.1-alpha.14", path = "../edlang_parser" }
|
||||
edlang_session = { version = "0.0.1-alpha.14", path = "../edlang_session" }
|
||||
tracing = { workspace = true }
|
||||
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
|
||||
walkdir = "2.5.0"
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = "3.10.1"
|
||||
|
|
|
@ -1,49 +1,60 @@
|
|||
use std::{path::PathBuf, time::Instant};
|
||||
|
||||
use anyhow::{bail, Result};
|
||||
use ariadne::Source;
|
||||
use anyhow::Result;
|
||||
use ariadne::{sources, Source};
|
||||
use clap::Parser;
|
||||
use edlang_codegen_llvm::linker::{link_binary, link_shared_lib};
|
||||
use edlang_lowering::lower_modules;
|
||||
use edlang_session::{DebugInfo, OptLevel, Session};
|
||||
use walkdir::WalkDir;
|
||||
|
||||
use crate::linker::{link_binary, link_shared_lib};
|
||||
|
||||
pub mod linker;
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(author, version, about = "edlang compiler driver", long_about = None, bin_name = "edlangc")]
|
||||
pub struct CompilerArgs {
|
||||
/// The input file.
|
||||
input: PathBuf,
|
||||
pub input: PathBuf,
|
||||
|
||||
/// The output file.
|
||||
pub output: PathBuf,
|
||||
|
||||
/// Build for release with all optimizations.
|
||||
#[arg(short, long, default_value_t = false)]
|
||||
release: bool,
|
||||
pub release: bool,
|
||||
|
||||
/// Set the optimization level, 0,1,2,3
|
||||
#[arg(short = 'O', long)]
|
||||
optlevel: Option<u8>,
|
||||
pub optlevel: Option<u8>,
|
||||
|
||||
/// Always add debug info
|
||||
#[arg(long)]
|
||||
debug_info: Option<bool>,
|
||||
pub debug_info: Option<bool>,
|
||||
|
||||
/// Build as a library.
|
||||
#[arg(short, long, default_value_t = false)]
|
||||
library: bool,
|
||||
pub library: bool,
|
||||
|
||||
/// Print the edlang AST
|
||||
#[arg(long, default_value_t = false)]
|
||||
ast: bool,
|
||||
pub ast: bool,
|
||||
|
||||
/// Print the edlang IR
|
||||
#[arg(long, default_value_t = false)]
|
||||
ir: bool,
|
||||
pub ir: bool,
|
||||
|
||||
/// Output llvm ir
|
||||
#[arg(long, default_value_t = false)]
|
||||
llvm: bool,
|
||||
pub llvm: bool,
|
||||
|
||||
/// Output asm
|
||||
#[arg(long, default_value_t = false)]
|
||||
asm: bool,
|
||||
pub asm: bool,
|
||||
|
||||
/// Output a object file
|
||||
#[arg(long, default_value_t = false)]
|
||||
pub object: bool,
|
||||
}
|
||||
|
||||
pub fn main() -> Result<()> {
|
||||
|
@ -51,51 +62,59 @@ pub fn main() -> Result<()> {
|
|||
|
||||
let args = CompilerArgs::parse();
|
||||
|
||||
compile_single_file(args)?;
|
||||
let object = compile(&args)?;
|
||||
|
||||
if args.library {
|
||||
link_shared_lib(&[object.clone()], &args.output)?;
|
||||
} else {
|
||||
link_binary(&[object.clone()], &args.output)?;
|
||||
}
|
||||
|
||||
if !args.object {
|
||||
std::fs::remove_file(object)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn compile_single_file(args: CompilerArgs) -> Result<()> {
|
||||
if !args.input.is_file() {
|
||||
bail!("Input is not a file");
|
||||
pub fn compile(args: &CompilerArgs) -> Result<PathBuf> {
|
||||
let mut files = Vec::new();
|
||||
for entry in WalkDir::new(&args.input) {
|
||||
let entry = entry?;
|
||||
if let Some(ext) = entry.path().extension() {
|
||||
if ext.eq_ignore_ascii_case("ed") {
|
||||
files.push(entry.path().to_path_buf());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if files.is_empty() {
|
||||
panic!("files is empty");
|
||||
}
|
||||
|
||||
let start_time = Instant::now();
|
||||
|
||||
tracing_subscriber::fmt::init();
|
||||
let mut modules = Vec::new();
|
||||
|
||||
let path = args.input.display().to_string();
|
||||
let source = std::fs::read_to_string(&args.input)?;
|
||||
for path in files {
|
||||
let source = std::fs::read_to_string(&path)?;
|
||||
|
||||
let modules = edlang_parser::parse_ast(&source);
|
||||
let modules_ast = edlang_parser::parse_ast(&source);
|
||||
|
||||
let modules = match modules {
|
||||
Ok(modules) => modules,
|
||||
Err(error) => {
|
||||
let report = edlang_parser::error_to_report(&path, &error)?;
|
||||
edlang_parser::print_report(&path, &source, report)?;
|
||||
std::process::exit(1)
|
||||
}
|
||||
};
|
||||
|
||||
let cwd = std::env::current_dir()?;
|
||||
// todo: find a better name, "target" would clash with rust if running in the source tree.
|
||||
let target_dir = cwd.join("target_ed/");
|
||||
if !target_dir.exists() {
|
||||
std::fs::create_dir_all(&target_dir)?;
|
||||
let modules_temp = match modules_ast {
|
||||
Ok(modules) => modules,
|
||||
Err(error) => {
|
||||
let path = path.display().to_string();
|
||||
let report = edlang_parser::error_to_report(&path, &error)?;
|
||||
edlang_parser::print_report(&path, &source, report)?;
|
||||
std::process::exit(1)
|
||||
}
|
||||
};
|
||||
modules.push((path, source, modules_temp));
|
||||
}
|
||||
let output_file = target_dir.join(PathBuf::from(args.input.file_name().unwrap()));
|
||||
let output_file = if args.library {
|
||||
output_file.with_extension(Session::get_platform_library_ext())
|
||||
} else if cfg!(target_os = "windows") {
|
||||
output_file.with_extension("exe")
|
||||
} else {
|
||||
output_file.with_extension("")
|
||||
};
|
||||
|
||||
let session = Session {
|
||||
file_path: args.input,
|
||||
file_paths: modules.iter().map(|x| x.0.clone()).collect(),
|
||||
debug_info: if let Some(debug_info) = args.debug_info {
|
||||
if debug_info {
|
||||
DebugInfo::Full
|
||||
|
@ -119,50 +138,50 @@ pub fn compile_single_file(args: CompilerArgs) -> Result<()> {
|
|||
} else {
|
||||
OptLevel::None
|
||||
},
|
||||
source: Source::from(source),
|
||||
sources: modules.iter().map(|x| Source::from(x.1.clone())).collect(),
|
||||
library: args.library,
|
||||
target_dir,
|
||||
output_file,
|
||||
output_file: args.output.with_extension("o"),
|
||||
output_asm: args.asm,
|
||||
output_llvm: args.llvm,
|
||||
};
|
||||
tracing::debug!("Input file: {:#?}", session.file_path);
|
||||
tracing::debug!("Target dir: {:#?}", session.target_dir);
|
||||
tracing::debug!("Output file: {:#?}", session.output_file);
|
||||
tracing::debug!("Is library: {:#?}", session.library);
|
||||
tracing::debug!("Optlevel: {:#?}", session.optlevel);
|
||||
tracing::debug!("Debug Info: {:#?}", session.debug_info);
|
||||
|
||||
let path_cache: Vec<_> = modules
|
||||
.iter()
|
||||
.map(|x| (x.0.display().to_string(), x.1.clone()))
|
||||
.collect();
|
||||
let modules: Vec<_> = modules.iter().map(|x| x.2.clone()).collect();
|
||||
|
||||
if args.ast {
|
||||
println!("{:#?}", modules);
|
||||
return Ok(());
|
||||
std::fs::write(
|
||||
session.output_file.with_extension("ast"),
|
||||
format!("{:#?}", modules),
|
||||
)?;
|
||||
}
|
||||
|
||||
let program_ir = match lower_modules(&modules) {
|
||||
Ok(ir) => ir,
|
||||
Err(error) => {
|
||||
let report = edlang_check::lowering_error_to_report(error, &session);
|
||||
let path = session.file_path.display().to_string();
|
||||
report.eprint((path, session.source.clone()))?;
|
||||
report.eprint(sources(path_cache))?;
|
||||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
if args.ir {
|
||||
println!("{:#?}", program_ir);
|
||||
return Ok(());
|
||||
std::fs::write(
|
||||
session.output_file.with_extension("ir"),
|
||||
format!("{:#?}", program_ir),
|
||||
)?;
|
||||
}
|
||||
|
||||
let object_path = edlang_codegen_llvm::compile(&session, &program_ir).unwrap();
|
||||
|
||||
if session.library {
|
||||
link_shared_lib(&object_path, &session.output_file)?;
|
||||
} else {
|
||||
link_binary(&object_path, &session.output_file)?;
|
||||
}
|
||||
|
||||
let elapsed = start_time.elapsed();
|
||||
tracing::debug!("Done in {:?}", elapsed);
|
||||
|
||||
Ok(())
|
||||
Ok(object_path)
|
||||
}
|
||||
|
|
|
@ -1,39 +1,41 @@
|
|||
use std::path::Path;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use tracing::instrument;
|
||||
|
||||
#[instrument(level = "debug")]
|
||||
pub fn link_shared_lib(input_path: &Path, output_filename: &Path) -> std::io::Result<()> {
|
||||
let args: &[&str] = {
|
||||
pub fn link_shared_lib(objects: &[PathBuf], output_filename: &Path) -> std::io::Result<()> {
|
||||
let objects: Vec<_> = objects.iter().map(|x| x.display().to_string()).collect();
|
||||
let output_filename = output_filename.to_string_lossy().to_string();
|
||||
|
||||
let args: Vec<_> = {
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
&[
|
||||
let mut args = vec![
|
||||
"-demangle",
|
||||
"-no_deduplicate",
|
||||
"-dynamic",
|
||||
"-dylib",
|
||||
"-L/usr/local/lib",
|
||||
"-L/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib",
|
||||
&input_path.display().to_string(),
|
||||
"-o",
|
||||
&output_filename.display().to_string(),
|
||||
"-lSystem",
|
||||
]
|
||||
];
|
||||
|
||||
args.extend(objects.iter().map(|x| x.as_str()));
|
||||
|
||||
args.extend(&["-o", &output_filename, "-lSystem"]);
|
||||
|
||||
args
|
||||
}
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
&[
|
||||
"--hash-style=gnu",
|
||||
"--eh-frame-hdr",
|
||||
"-shared",
|
||||
"-o",
|
||||
&output_filename.display().to_string(),
|
||||
"-L/lib/../lib64",
|
||||
"-L/usr/lib/../lib64",
|
||||
"-lc",
|
||||
"-O1",
|
||||
&input_path.display().to_string(),
|
||||
]
|
||||
let mut args = vec!["--hash-style=gnu", "--eh-frame-hdr", "-shared"];
|
||||
|
||||
args.extend(&["-o", &output_filename]);
|
||||
|
||||
args.extend(&["-L/lib/../lib64", "-L/usr/lib/../lib64", "-lc", "-O1"]);
|
||||
|
||||
args.extend(objects.iter().map(|x| x.as_str()));
|
||||
|
||||
args
|
||||
}
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
|
@ -48,18 +50,24 @@ pub fn link_shared_lib(input_path: &Path, output_filename: &Path) -> std::io::Re
|
|||
}
|
||||
|
||||
#[instrument(level = "debug")]
|
||||
pub fn link_binary(input_path: &Path, output_filename: &Path) -> std::io::Result<()> {
|
||||
let args: &[&str] = {
|
||||
pub fn link_binary(objects: &[PathBuf], output_filename: &Path) -> std::io::Result<()> {
|
||||
let objects: Vec<_> = objects.iter().map(|x| x.display().to_string()).collect();
|
||||
let output_filename = output_filename.to_string_lossy().to_string();
|
||||
|
||||
let args: Vec<_> = {
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
&[
|
||||
let mut args = vec![
|
||||
"-L/usr/local/lib",
|
||||
"-L/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib",
|
||||
&input_path.display().to_string(),
|
||||
"-o",
|
||||
&output_filename.display().to_string(),
|
||||
"-lSystem",
|
||||
]
|
||||
];
|
||||
|
||||
args.extend(objects.iter().map(|x| x.as_str()));
|
||||
|
||||
args.extend(&["-o", &output_filename, "-lSystem"]);
|
||||
|
||||
args
|
||||
}
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
|
@ -79,7 +87,7 @@ pub fn link_binary(input_path: &Path, output_filename: &Path) -> std::io::Result
|
|||
}
|
||||
};
|
||||
|
||||
&[
|
||||
let mut args = vec![
|
||||
"-pie",
|
||||
"--hash-style=gnu",
|
||||
"--eh-frame-hdr",
|
||||
|
@ -89,8 +97,11 @@ pub fn link_binary(input_path: &Path, output_filename: &Path) -> std::io::Result
|
|||
"elf_x86_64",
|
||||
scrt1,
|
||||
crti,
|
||||
"-o",
|
||||
&output_filename.display().to_string(),
|
||||
];
|
||||
|
||||
args.extend(&["-o", &output_filename]);
|
||||
|
||||
args.extend(&[
|
||||
"-L/lib64",
|
||||
"-L/usr/lib64",
|
||||
"-L/lib/x86_64-linux-gnu",
|
||||
|
@ -99,8 +110,11 @@ pub fn link_binary(input_path: &Path, output_filename: &Path) -> std::io::Result
|
|||
"-lc",
|
||||
"-O1",
|
||||
crtn,
|
||||
&input_path.display().to_string(),
|
||||
]
|
||||
]);
|
||||
|
||||
args.extend(objects.iter().map(|x| x.as_str()));
|
||||
|
||||
args
|
||||
}
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
|
@ -6,7 +6,7 @@ use std::{
|
|||
};
|
||||
|
||||
use ariadne::Source;
|
||||
use edlang_codegen_llvm::linker::{link_binary, link_shared_lib};
|
||||
use edlang_driver::linker::{link_binary, link_shared_lib};
|
||||
use edlang_lowering::lower_modules;
|
||||
use edlang_session::{DebugInfo, OptLevel, Session};
|
||||
use tempfile::TempDir;
|
||||
|
@ -36,13 +36,9 @@ pub fn compile_program(
|
|||
) -> Result<CompileResult, Box<dyn std::error::Error>> {
|
||||
let modules = edlang_parser::parse_ast(source).unwrap();
|
||||
|
||||
let test_dir = tempfile::tempdir()?;
|
||||
let test_dir_path = test_dir.path();
|
||||
let target_dir = test_dir_path.join("build_artifacts/");
|
||||
if !target_dir.exists() {
|
||||
std::fs::create_dir_all(&target_dir)?;
|
||||
}
|
||||
let output_file = target_dir.join(PathBuf::from(name));
|
||||
let test_dir = tempfile::tempdir().unwrap();
|
||||
let test_dir_path = test_dir.path().canonicalize()?;
|
||||
let output_file = test_dir_path.join(PathBuf::from(name));
|
||||
let output_file = if library {
|
||||
output_file.with_extension(Session::get_platform_library_ext())
|
||||
} else if cfg!(target_os = "windows") {
|
||||
|
@ -51,26 +47,28 @@ pub fn compile_program(
|
|||
output_file.with_extension("")
|
||||
};
|
||||
|
||||
let input_file = output_file.with_extension("ed");
|
||||
std::fs::write(&input_file, source)?;
|
||||
|
||||
let session = Session {
|
||||
file_path: PathBuf::from(name),
|
||||
file_paths: vec![input_file],
|
||||
debug_info: DebugInfo::Full,
|
||||
optlevel: OptLevel::Default,
|
||||
source: Source::from(source.to_string()),
|
||||
sources: vec![Source::from(source.to_string())],
|
||||
library,
|
||||
target_dir,
|
||||
output_file,
|
||||
output_llvm: false,
|
||||
output_asm: false,
|
||||
};
|
||||
|
||||
let program_ir = lower_modules(&modules)?;
|
||||
let program_ir = lower_modules(&[modules]).unwrap();
|
||||
|
||||
let object_path = edlang_codegen_llvm::compile(&session, &program_ir)?;
|
||||
let object_path = edlang_codegen_llvm::compile(&session, &program_ir).unwrap();
|
||||
|
||||
if library {
|
||||
link_shared_lib(&object_path, &session.output_file)?;
|
||||
link_shared_lib(&[object_path.clone()], &session.output_file).unwrap();
|
||||
} else {
|
||||
link_binary(&object_path, &session.output_file)?;
|
||||
link_binary(&[object_path.clone()], &session.output_file).unwrap();
|
||||
}
|
||||
|
||||
Ok(CompileResult {
|
||||
|
@ -81,5 +79,5 @@ pub fn compile_program(
|
|||
}
|
||||
|
||||
pub fn run_program(program: &Path, args: &[&str]) -> Result<Child, std::io::Error> {
|
||||
std::process::Command::new(dbg!(program)).args(args).spawn()
|
||||
std::process::Command::new(program).args(args).spawn()
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "edlang_ir"
|
||||
version = "0.0.1-alpha.12"
|
||||
version = "0.0.1-alpha.14"
|
||||
authors = ["Edgar Luque <edgar@edgarluque.com>"]
|
||||
description = "edlang IR"
|
||||
edition = "2021"
|
||||
|
@ -13,6 +13,6 @@ repository = "https://github.com/edg-l/edlang"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
edlang_span = { version = "0.0.1-alpha.12", path = "../edlang_span" }
|
||||
edlang_span = { version = "0.0.1-alpha.14", path = "../edlang_span" }
|
||||
smallvec = "1.13.1"
|
||||
educe = "0.5.11"
|
||||
|
|
|
@ -39,6 +39,7 @@ pub struct ProgramBody {
|
|||
pub struct ModuleBody {
|
||||
pub module_id: DefId,
|
||||
pub parent_ids: Vec<DefId>,
|
||||
pub file_id: usize,
|
||||
pub name: String,
|
||||
pub symbols: SymbolTable,
|
||||
/// Functions defined in this module.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "edlang_lowering"
|
||||
version = "0.0.1-alpha.12"
|
||||
version = "0.0.1-alpha.14"
|
||||
authors = ["Edgar Luque <edgar@edgarluque.com>"]
|
||||
description = "edlang lowering"
|
||||
edition = "2021"
|
||||
|
@ -13,7 +13,7 @@ repository = "https://github.com/edg-l/edlang"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
edlang_ast = { version = "0.0.1-alpha.12", path = "../edlang_ast" }
|
||||
edlang_ir = { version = "0.0.1-alpha.12", path = "../edlang_ir" }
|
||||
edlang_ast = { version = "0.0.1-alpha.14", path = "../edlang_ast" }
|
||||
edlang_ir = { version = "0.0.1-alpha.14", path = "../edlang_ir" }
|
||||
tracing.workspace = true
|
||||
thiserror = "1.0.57"
|
||||
|
|
|
@ -60,6 +60,7 @@ pub struct BodyBuilder {
|
|||
pub statements: Vec<Statement>,
|
||||
pub name_to_local: HashMap<String, usize>,
|
||||
pub ret_local: usize,
|
||||
pub file_id: usize,
|
||||
pub ctx: BuildCtx,
|
||||
}
|
||||
|
||||
|
|
|
@ -7,33 +7,60 @@ use crate::DefId;
|
|||
#[derive(Debug, Error, Clone)]
|
||||
pub enum LoweringError {
|
||||
#[error("module {module:?} not found")]
|
||||
ModuleNotFound { span: Span, module: String },
|
||||
ModuleNotFound {
|
||||
span: Span,
|
||||
module: String,
|
||||
file_id: usize,
|
||||
},
|
||||
#[error("function {function:?} not found")]
|
||||
FunctionNotFound { span: Span, function: String },
|
||||
FunctionNotFound {
|
||||
span: Span,
|
||||
function: String,
|
||||
file_id: usize,
|
||||
},
|
||||
#[error("symbol {:?} not found", symbol.name)]
|
||||
ImportNotFound {
|
||||
module_span: Span,
|
||||
import_span: Span,
|
||||
symbol: Ident,
|
||||
file_id: usize,
|
||||
},
|
||||
#[error("trying to mutate a non-mutable reference")]
|
||||
BorrowNotMutable {
|
||||
span: Span,
|
||||
type_span: Option<Span>,
|
||||
name: String,
|
||||
file_id: usize,
|
||||
},
|
||||
#[error("unrecognized type {name}")]
|
||||
UnrecognizedType { span: Span, name: String },
|
||||
UnrecognizedType {
|
||||
span: Span,
|
||||
name: String,
|
||||
file_id: usize,
|
||||
},
|
||||
#[error("id not found")]
|
||||
IdNotFound { span: Span, id: DefId },
|
||||
IdNotFound {
|
||||
span: Span,
|
||||
id: DefId,
|
||||
file_id: usize,
|
||||
},
|
||||
#[error("feature not yet implemented: {message}")]
|
||||
NotYetImplemented { span: Span, message: &'static str },
|
||||
NotYetImplemented {
|
||||
span: Span,
|
||||
message: &'static str,
|
||||
file_id: usize,
|
||||
},
|
||||
#[error("unexpected type")]
|
||||
UnexpectedType {
|
||||
span: Span,
|
||||
found: TypeKind,
|
||||
expected: TypeInfo,
|
||||
file_id: usize,
|
||||
},
|
||||
#[error("use of underclared variable {name:?}")]
|
||||
UseOfUndeclaredVariable { span: Span, name: String },
|
||||
UseOfUndeclaredVariable {
|
||||
span: Span,
|
||||
name: String,
|
||||
file_id: usize,
|
||||
},
|
||||
}
|
||||
|
|
|
@ -15,27 +15,33 @@ mod common;
|
|||
pub mod errors;
|
||||
mod prepass;
|
||||
|
||||
pub fn lower_modules(modules: &[ast::Module]) -> Result<ProgramBody, LoweringError> {
|
||||
pub fn lower_modules(modules: &[Vec<ast::Module>]) -> Result<ProgramBody, LoweringError> {
|
||||
let mut ctx = BuildCtx::default();
|
||||
|
||||
// resolve symbols
|
||||
for module in modules {
|
||||
ctx = prepass::prepass_module(ctx, module)?;
|
||||
for (file_id, modules) in modules.iter().enumerate() {
|
||||
for module in modules {
|
||||
ctx = prepass::prepass_module(ctx, module, file_id)?;
|
||||
}
|
||||
}
|
||||
|
||||
// resolve imports
|
||||
for module in modules {
|
||||
ctx = prepass::prepass_imports(ctx, module)?;
|
||||
for (file_id, modules) in modules.iter().enumerate() {
|
||||
for module in modules {
|
||||
ctx = prepass::prepass_imports(ctx, module, file_id)?;
|
||||
}
|
||||
}
|
||||
|
||||
for mod_def in modules {
|
||||
let id = *ctx
|
||||
.body
|
||||
.top_level_module_names
|
||||
.get(&mod_def.name.name)
|
||||
.expect("module should exist");
|
||||
for modules in modules {
|
||||
for mod_def in modules {
|
||||
let id = *ctx
|
||||
.body
|
||||
.top_level_module_names
|
||||
.get(&mod_def.name.name)
|
||||
.expect("module should exist");
|
||||
|
||||
ctx = lower_module(ctx, mod_def, id)?;
|
||||
ctx = lower_module(ctx, mod_def, id)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(ctx.body)
|
||||
|
@ -157,6 +163,10 @@ fn lower_function(
|
|||
ret_local: 0,
|
||||
name_to_local: HashMap::new(),
|
||||
statements: Vec::new(),
|
||||
file_id: {
|
||||
let body = ctx.body.modules.get(&module_id).unwrap();
|
||||
body.file_id
|
||||
},
|
||||
ctx,
|
||||
};
|
||||
|
||||
|
@ -450,6 +460,7 @@ fn lower_let(builder: &mut BodyBuilder, info: &ast::LetStmt) -> Result<(), Lower
|
|||
span: info.span,
|
||||
found: found_ty,
|
||||
expected: ty.clone(),
|
||||
file_id: builder.file_id,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -781,6 +792,7 @@ fn lower_binary_expr(
|
|||
span: Some(lhs_span),
|
||||
kind: lhs_ty,
|
||||
},
|
||||
file_id: builder.file_id,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1112,6 +1124,7 @@ fn lower_return(
|
|||
span,
|
||||
found: ty,
|
||||
expected: return_type.clone(),
|
||||
file_id: builder.file_id,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1145,6 +1158,7 @@ fn lower_path(
|
|||
LoweringError::UseOfUndeclaredVariable {
|
||||
span: info.span,
|
||||
name: info.first.name.clone(),
|
||||
file_id: builder.file_id,
|
||||
},
|
||||
)?;
|
||||
|
||||
|
@ -1256,6 +1270,7 @@ pub fn lower_type(
|
|||
Err(LoweringError::UnrecognizedType {
|
||||
span: t.name.span,
|
||||
name: t.name.name.clone(),
|
||||
file_id: module.file_id,
|
||||
})?
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,11 @@ use super::common::BuildCtx;
|
|||
use edlang_ast as ast;
|
||||
use edlang_ir::ModuleBody;
|
||||
|
||||
pub fn prepass_module(mut ctx: BuildCtx, mod_def: &ast::Module) -> Result<BuildCtx, LoweringError> {
|
||||
pub fn prepass_module(
|
||||
mut ctx: BuildCtx,
|
||||
mod_def: &ast::Module,
|
||||
file_id: usize,
|
||||
) -> Result<BuildCtx, LoweringError> {
|
||||
let module_id = ctx.gen.next_defid();
|
||||
tracing::debug!("running ir prepass on module {:?}", module_id);
|
||||
|
||||
|
@ -29,6 +33,7 @@ pub fn prepass_module(mut ctx: BuildCtx, mod_def: &ast::Module) -> Result<BuildC
|
|||
constants: Default::default(),
|
||||
imports: Default::default(),
|
||||
span: mod_def.span,
|
||||
file_id,
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -106,7 +111,7 @@ pub fn prepass_module(mut ctx: BuildCtx, mod_def: &ast::Module) -> Result<BuildC
|
|||
.expect("module should exist");
|
||||
|
||||
let next_id = *current_module.symbols.modules.get(&info.name.name).unwrap();
|
||||
ctx = prepass_sub_module(ctx, &[module_id], next_id, info)?;
|
||||
ctx = prepass_sub_module(ctx, &[module_id], next_id, info, file_id)?;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -118,6 +123,7 @@ pub fn prepass_sub_module(
|
|||
parent_ids: &[DefId],
|
||||
module_id: DefId,
|
||||
mod_def: &ast::Module,
|
||||
file_id: usize,
|
||||
) -> Result<BuildCtx, LoweringError> {
|
||||
tracing::debug!("running ir prepass on submodule {:?}", module_id);
|
||||
let mut submodule_parents_ids = parent_ids.to_vec();
|
||||
|
@ -137,6 +143,7 @@ pub fn prepass_sub_module(
|
|||
types: Default::default(),
|
||||
constants: Default::default(),
|
||||
span: mod_def.span,
|
||||
file_id,
|
||||
};
|
||||
|
||||
for ct in &mod_def.contents {
|
||||
|
@ -201,7 +208,7 @@ pub fn prepass_sub_module(
|
|||
for ct in &mod_def.contents {
|
||||
if let ast::ModuleStatement::Module(info) = ct {
|
||||
let next_id = ctx.gen.next_defid();
|
||||
ctx = prepass_sub_module(ctx, &submodule_parents_ids, next_id, info)?;
|
||||
ctx = prepass_sub_module(ctx, &submodule_parents_ids, next_id, info, file_id)?;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -211,6 +218,7 @@ pub fn prepass_sub_module(
|
|||
pub fn prepass_imports(
|
||||
mut ctx: BuildCtx,
|
||||
mod_def: &ast::Module,
|
||||
file_id: usize,
|
||||
) -> Result<BuildCtx, LoweringError> {
|
||||
let mod_id = *ctx
|
||||
.body
|
||||
|
@ -226,6 +234,7 @@ pub fn prepass_imports(
|
|||
.ok_or_else(|| LoweringError::ModuleNotFound {
|
||||
span: import.module[0].span,
|
||||
module: import.module[0].name.clone(),
|
||||
file_id,
|
||||
})?;
|
||||
let mut imported_module =
|
||||
ctx.body
|
||||
|
@ -234,6 +243,7 @@ pub fn prepass_imports(
|
|||
.ok_or(LoweringError::IdNotFound {
|
||||
span: mod_def.span,
|
||||
id: *imported_module_id,
|
||||
file_id,
|
||||
})?;
|
||||
|
||||
for module_path in import.module.iter().skip(1) {
|
||||
|
@ -244,11 +254,13 @@ pub fn prepass_imports(
|
|||
.ok_or_else(|| LoweringError::ModuleNotFound {
|
||||
span: module_path.span,
|
||||
module: module_path.name.clone(),
|
||||
file_id,
|
||||
})?;
|
||||
imported_module = ctx.body.modules.get(imported_module_id).ok_or({
|
||||
LoweringError::IdNotFound {
|
||||
span: module_path.span,
|
||||
id: *imported_module_id,
|
||||
file_id,
|
||||
}
|
||||
})?;
|
||||
}
|
||||
|
@ -269,6 +281,7 @@ pub fn prepass_imports(
|
|||
module_span: mod_def.span,
|
||||
import_span: import.span,
|
||||
symbol: sym.clone(),
|
||||
file_id,
|
||||
})?;
|
||||
}
|
||||
}
|
||||
|
@ -283,7 +296,7 @@ pub fn prepass_imports(
|
|||
|
||||
for c in &mod_def.contents {
|
||||
if let ast::ModuleStatement::Module(info) = c {
|
||||
ctx = prepass_imports_submodule(ctx, info, mod_id)?;
|
||||
ctx = prepass_imports_submodule(ctx, info, mod_id, file_id)?;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -294,6 +307,7 @@ pub fn prepass_imports_submodule(
|
|||
mut ctx: BuildCtx,
|
||||
mod_def: &ast::Module,
|
||||
parent_id: DefId,
|
||||
file_id: usize,
|
||||
) -> Result<BuildCtx, LoweringError> {
|
||||
let mod_id = *ctx
|
||||
.body
|
||||
|
@ -306,6 +320,7 @@ pub fn prepass_imports_submodule(
|
|||
.ok_or_else(|| LoweringError::ModuleNotFound {
|
||||
span: mod_def.span,
|
||||
module: mod_def.name.name.clone(),
|
||||
file_id,
|
||||
})?;
|
||||
|
||||
for import in &mod_def.imports {
|
||||
|
@ -316,11 +331,13 @@ pub fn prepass_imports_submodule(
|
|||
.ok_or_else(|| LoweringError::ModuleNotFound {
|
||||
span: import.module[0].span,
|
||||
module: import.module[0].name.clone(),
|
||||
file_id,
|
||||
})?;
|
||||
let mut imported_module = ctx.body.modules.get(imported_module_id).ok_or_else(|| {
|
||||
LoweringError::ModuleNotFound {
|
||||
span: import.module[0].span,
|
||||
module: import.module[0].name.clone(),
|
||||
file_id,
|
||||
}
|
||||
})?;
|
||||
|
||||
|
@ -332,11 +349,13 @@ pub fn prepass_imports_submodule(
|
|||
.ok_or_else(|| LoweringError::ModuleNotFound {
|
||||
span: module_path.span,
|
||||
module: module_path.name.clone(),
|
||||
file_id,
|
||||
})?;
|
||||
imported_module = ctx.body.modules.get(imported_module_id).ok_or({
|
||||
LoweringError::IdNotFound {
|
||||
span: import.span,
|
||||
id: *imported_module_id,
|
||||
file_id,
|
||||
}
|
||||
})?;
|
||||
}
|
||||
|
@ -357,6 +376,7 @@ pub fn prepass_imports_submodule(
|
|||
module_span: mod_def.span,
|
||||
import_span: import.span,
|
||||
symbol: sym.clone(),
|
||||
file_id,
|
||||
})?;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "edlang_parser"
|
||||
version = "0.0.1-alpha.12"
|
||||
version = "0.0.1-alpha.14"
|
||||
authors = ["Edgar Luque <edgar@edgarluque.com>"]
|
||||
description = "edlang parser"
|
||||
edition = "2021"
|
||||
|
@ -14,7 +14,7 @@ repository = "https://github.com/edg-l/edlang"
|
|||
|
||||
[dependencies]
|
||||
ariadne = { version = "0.4.0", features = ["auto-color"] }
|
||||
edlang_ast = { version = "0.0.1-alpha.12", path = "../edlang_ast" }
|
||||
edlang_ast = { version = "0.0.1-alpha.14", path = "../edlang_ast" }
|
||||
itertools = "0.12.0"
|
||||
lalrpop-util = { version = "0.20.0", features = ["lexer"] }
|
||||
logos = "0.14.0"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "edlang_session"
|
||||
version = "0.0.1-alpha.12"
|
||||
version = "0.0.1-alpha.14"
|
||||
authors = ["Edgar Luque <edgar@edgarluque.com>"]
|
||||
description = "edlang session"
|
||||
edition = "2021"
|
||||
|
|
|
@ -4,13 +4,11 @@ use ariadne::Source;
|
|||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Session {
|
||||
pub file_path: PathBuf,
|
||||
pub file_paths: Vec<PathBuf>,
|
||||
pub debug_info: DebugInfo,
|
||||
pub optlevel: OptLevel,
|
||||
pub source: Source<String>,
|
||||
pub sources: Vec<Source<String>>,
|
||||
pub library: bool,
|
||||
/// The directory where to store artifacts and intermediate files such as object files.
|
||||
pub target_dir: PathBuf,
|
||||
pub output_file: PathBuf,
|
||||
pub output_llvm: bool,
|
||||
pub output_asm: bool,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "edlang_span"
|
||||
version = "0.0.1-alpha.12"
|
||||
version = "0.0.1-alpha.14"
|
||||
authors = ["Edgar Luque <edgar@edgarluque.com>"]
|
||||
description = "edlang span"
|
||||
edition = "2021"
|
||||
|
|
Loading…
Reference in a new issue