adding null

This commit is contained in:
Jakub Doka 2024-10-27 19:55:11 +01:00
parent 2c2f0c048b
commit 047e1ed15c
No known key found for this signature in database
GPG key ID: C6E9A89936B8C143
5 changed files with 46 additions and 11 deletions

View file

@ -18,7 +18,6 @@ Holey-Bytes-Language (hblang for short) (*.hb) is the only true language targeti
hblang knows what it isn't, because it knows what it is, hblang computes this by sub...
## Examples
Examples are also used in tests. To add an example that runs during testing add:
@ -30,9 +29,9 @@ Examples are also used in tests. To add an example that runs during testing add:
</pre>
and also:
```rs
<name> => README;
<name>;
```
to the `run_tests` macro at the bottom of the `src/codegen.rs`.
to the `run_tests` macro at the bottom of the `src/son.rs`.
### Tour Examples
@ -129,6 +128,9 @@ fib := fn(n: uint): uint {
#### pointers
```hb
main := fn(): uint {
n := @as(^uint, null)
if n != null return 9001
a := 1
b := &a
@ -289,14 +291,14 @@ foo := fn(): uint return 0
arbitrary text
```
- `@use(<string>)`: imports a module based of string, the string is passed to a loader that can be customized, default loader uses following syntax:
- `((rel:|)(<path>)|git:<git-addr>:<path>)`: `rel:` and `''` prefixes both mean module is located at `path` relavive to the current file, `git:` takes a git url without `https://` passed as `git-addr`, `path` then refers to file within the repository
- `@use(<string>)`: imports a module based on relative path, cycles are allowed when importing
- `@TypeOf(<expr>)`: results into literal type of whatever the type of `<expr>` is, `<expr>` is not included in final binary
- `@as(<ty>, <expr>)`: huint to the compiler that `@TypeOf(<expr>) == <ty>`
- `@as(<ty>, <expr>)`: hint to the compiler that `@TypeOf(<expr>) == <ty>`
- `@intcast(<expr>)`: needs to be used when conversion of `@TypeOf(<expr>)` would loose precision (widening of integers is implicit)
- `@sizeof(<ty>), @alignof(<ty>)`: I think explaining this would insult your intelligence
- `@bitcast(<expr>)`: tell compiler to assume `@TypeOf(<expr>)` is whatever is inferred, so long as size and alignment did not change
- `@eca(<ty>, ...<expr>)`: invoke `eca` instruction, where `<ty>` is the type this will return and `<expr>...` are arguments passed to the call
- `@sizeof(<ty>), @alignof(<ty>)`: get size and align of a type in bytes
- `@bitcast(<expr>)`: tell compiler to assume `@TypeOf(<expr>)` is whatever is inferred, so long as size matches
- `@eca(...<expr>)`: invoke `eca` instruction, where return type is inferred and `<expr>...` are arguments passed to the call in the standard call convention
- `@embed(<string>)`: include relative file as an array of bytes
- `@inline(<func>, ...<args>)`: equivalent to `<func>(...<args>)` but function is guaranteed to inline, compiler will otherwise never inline
#### c_strings
@ -396,6 +398,7 @@ main := fn(): uint {
return big_array[42]
}
```
note: this does not work on scalar values
#### generic_functions
```hb

View file

@ -368,6 +368,7 @@ impl<'a> Formatter<'a> {
}
Expr::Bool { value, .. } => f.write_str(if value { "true" } else { "false" }),
Expr::Idk { .. } => f.write_str("idk"),
Expr::Null { .. } => f.write_str("null"),
Expr::BinOp {
left,
op: TokenKind::Assign,

View file

@ -131,6 +131,7 @@ pub enum TokenKind {
Packed,
True,
False,
Null,
Idk,
Ctor,
@ -267,7 +268,8 @@ gen_token_kind! {
Packed = b"packed",
True = b"true",
False = b"false",
Idk = b"idk",
Null = b"null",
Idk = b"idk",
#[punkt]
Ctor = ".{",
Tupl = ".(",

View file

@ -335,6 +335,7 @@ impl<'a, 'b> Parser<'a, 'b> {
},
T::True => E::Bool { pos, value: true },
T::False => E::Bool { pos, value: false },
T::Null => E::Null { pos },
T::Idk => E::Idk { pos },
T::DQuote => E::String { pos, literal: self.tok_str(token) },
T::Packed => {
@ -881,6 +882,10 @@ generate_expr! {
pos: Pos,
value: bool,
},
/// `'null'`
Null {
pos: Pos,
},
/// `'idk'`
Idk {
pos: Pos,

View file

@ -1714,6 +1714,30 @@ impl<'a> Codegen<'a> {
fn raw_expr_ctx(&mut self, expr: &Expr, ctx: Ctx) -> Option<Value> {
// ordered by complexity of the expression
match *expr {
Expr::Null { pos } => {
let Some(ty) = ctx.ty else {
self.report(
pos,
"resulting pointer cannot be inferred from context, \
consider using `@as(^<ty>, null)` to hint the type",
);
return Value::NEVER;
};
if !ty.is_pointer() {
self.report(
pos,
fa!(
"'null' expression was inferred to be '{}',
which is not a pointer (and that is not supported yet)",
self.ty_display(ty)
),
);
return Value::NEVER;
}
Some(self.ci.nodes.new_node_lit(ty, Kind::CInt { value: 0 }, [VOID]))
}
Expr::Idk { pos } => {
let Some(ty) = ctx.ty else {
self.report(
@ -2812,7 +2836,7 @@ impl<'a> Codegen<'a> {
}
ref e => {
self.report_unhandled_ast(e, "bruh");
Some(Value::VOID)
Value::NEVER
}
}
}