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... hblang knows what it isn't, because it knows what it is, hblang computes this by sub...
## Examples ## Examples
Examples are also used in tests. To add an example that runs during testing add: 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> </pre>
and also: and also:
```rs ```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 ### Tour Examples
@ -129,6 +128,9 @@ fib := fn(n: uint): uint {
#### pointers #### pointers
```hb ```hb
main := fn(): uint { main := fn(): uint {
n := @as(^uint, null)
if n != null return 9001
a := 1 a := 1
b := &a b := &a
@ -289,14 +291,14 @@ foo := fn(): uint return 0
arbitrary text 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: - `@use(<string>)`: imports a module based on relative path, cycles are allowed when importing
- `((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
- `@TypeOf(<expr>)`: results into literal type of whatever the type of `<expr>` is, `<expr>` is not included in final binary - `@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) - `@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 - `@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 and alignment did not change - `@bitcast(<expr>)`: tell compiler to assume `@TypeOf(<expr>)` is whatever is inferred, so long as size matches
- `@eca(<ty>, ...<expr>)`: invoke `eca` instruction, where `<ty>` is the type this will return and `<expr>...` are arguments passed to the call - `@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 - `@inline(<func>, ...<args>)`: equivalent to `<func>(...<args>)` but function is guaranteed to inline, compiler will otherwise never inline
#### c_strings #### c_strings
@ -396,6 +398,7 @@ main := fn(): uint {
return big_array[42] return big_array[42]
} }
``` ```
note: this does not work on scalar values
#### generic_functions #### generic_functions
```hb ```hb

View file

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

View file

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

View file

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

View file

@ -1714,6 +1714,30 @@ impl<'a> Codegen<'a> {
fn raw_expr_ctx(&mut self, expr: &Expr, ctx: Ctx) -> Option<Value> { fn raw_expr_ctx(&mut self, expr: &Expr, ctx: Ctx) -> Option<Value> {
// ordered by complexity of the expression // ordered by complexity of the expression
match *expr { 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 } => { Expr::Idk { pos } => {
let Some(ty) = ctx.ty else { let Some(ty) = ctx.ty else {
self.report( self.report(
@ -2812,7 +2836,7 @@ impl<'a> Codegen<'a> {
} }
ref e => { ref e => {
self.report_unhandled_ast(e, "bruh"); self.report_unhandled_ast(e, "bruh");
Some(Value::VOID) Value::NEVER
} }
} }
} }