Skip to content

Commit

Permalink
Add support for interfacing with C libraries
Browse files Browse the repository at this point in the history
This adds support for linking against C libraries and using their types
and functions. The FFI is fairly strict and a bit limited, such as not
performing automatic type conversions, but this is a deliberate choice:
it keeps the compiler's complexity at a reasonable level, and it should
(hopefully) further drive home the idea that one should avoid
interfacing with C as much as they can, as all of Inko's safety
guarantees are thrown out of the window when doing so.

In preparation for #525, some
runtime functions return an i64 instead of an Int, while some still
return an Int. This is a little inconsistent, but the goal is to try and
reduce the amount of explicit type casts that we may need to change when
said specialisation is implemented. Once implemented, Int64 will just be
an alias for Int (or maybe I'll remove it entirely, not sure yet).

As part of this work, the precedence of type casts (`x as Type`) is
changed to be the same as binary operators. This means expressions such
as `x as Foo + y` are now valid, instead of resulting in a syntax error.
This makes working with type casts (something you'll need to use more
often when working with C code) less painful.

This commit also introduces support for conditional compilation at the
import level. Based on the build target, a set of build tags is
produced. `import` statements support a condition, and when given the
`import` is only included if all the tags match. For example:

    import foo if mac and amd64

This would only import `foo` if the tags "mac" and "amd64" are present.
OR and NOT expressions aren't supported, as one can simply use multiple
imports.

This fixes #290.

Changelog: added
  • Loading branch information
yorickpeterse committed Jul 9, 2023
1 parent 59578a1 commit b76aa9a
Show file tree
Hide file tree
Showing 85 changed files with 5,311 additions and 6,406 deletions.
5 changes: 5 additions & 0 deletions ast/src/lexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ pub enum TokenKind {
UnsignedShrAssign,
While,
Whitespace,
Extern,
}

impl TokenKind {
Expand Down Expand Up @@ -274,6 +275,7 @@ impl TokenKind {
TokenKind::Recover => "the 'recover' keyword",
TokenKind::Nil => "the 'nil' keyword",
TokenKind::Replace => "a '=:'",
TokenKind::Extern => "the 'extern' keyword",
}
}
}
Expand Down Expand Up @@ -340,6 +342,7 @@ impl Token {
| TokenKind::False
| TokenKind::Case
| TokenKind::Enum
| TokenKind::Extern
)
}

Expand Down Expand Up @@ -995,6 +998,7 @@ impl Lexer {
"import" => TokenKind::Import,
"return" => TokenKind::Return,
"static" => TokenKind::Static,
"extern" => TokenKind::Extern,
_ => TokenKind::Identifier,
},
7 => match value.as_str() {
Expand Down Expand Up @@ -2073,6 +2077,7 @@ mod tests {
assert_token!("import", Import, "import", 1..=1, 1..=6);
assert_token!("return", Return, "return", 1..=1, 1..=6);
assert_token!("static", Static, "static", 1..=1, 1..=6);
assert_token!("extern", Extern, "extern", 1..=1, 1..=6);

assert_token!("builtin", Builtin, "builtin", 1..=1, 1..=7);
assert_token!("recover", Recover, "recover", 1..=1, 1..=7);
Expand Down
36 changes: 36 additions & 0 deletions ast/src/nodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -324,11 +324,25 @@ impl Node for ImportPath {
}
}

#[derive(Debug, PartialEq, Eq)]
pub struct BuildTags {
pub values: Vec<Identifier>,
pub location: SourceLocation,
}

impl Node for BuildTags {
fn location(&self) -> &SourceLocation {
&self.location
}
}

#[derive(Debug, PartialEq, Eq)]
pub struct Import {
pub path: ImportPath,
pub symbols: Option<ImportSymbols>,
pub location: SourceLocation,
pub tags: Option<BuildTags>,
pub include: bool,
}

impl Node for Import {
Expand All @@ -337,6 +351,24 @@ impl Node for Import {
}
}

#[derive(Debug, PartialEq, Eq)]
pub struct ExternImportPath {
pub path: String,
pub location: SourceLocation,
}

#[derive(Debug, PartialEq, Eq)]
pub struct ExternImport {
pub path: ExternImportPath,
pub location: SourceLocation,
}

impl Node for ExternImport {
fn location(&self) -> &SourceLocation {
&self.location
}
}

#[derive(Debug, PartialEq, Eq)]
pub struct DefineConstant {
pub public: bool,
Expand All @@ -359,6 +391,7 @@ pub enum MethodKind {
Moving,
Mutable,
AsyncMutable,
Extern,
}

#[derive(Debug, PartialEq, Eq)]
Expand Down Expand Up @@ -419,6 +452,7 @@ pub enum ClassKind {
Builtin,
Enum,
Regular,
Extern,
}

#[derive(Debug, PartialEq, Eq)]
Expand Down Expand Up @@ -501,6 +535,7 @@ pub enum TopLevelExpression {
ReopenClass(Box<ReopenClass>),
ImplementTrait(Box<ImplementTrait>),
Import(Box<Import>),
ExternImport(Box<ExternImport>),
}

impl Node for TopLevelExpression {
Expand All @@ -513,6 +548,7 @@ impl Node for TopLevelExpression {
TopLevelExpression::ReopenClass(ref typ) => typ.location(),
TopLevelExpression::ImplementTrait(ref typ) => typ.location(),
TopLevelExpression::Import(ref typ) => typ.location(),
TopLevelExpression::ExternImport(ref typ) => typ.location(),
}
}
}
Expand Down
Loading

0 comments on commit b76aa9a

Please sign in to comment.