forked from AbleOS/holey-bytes
adding null
This commit is contained in:
parent
2c2f0c048b
commit
047e1ed15c
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -131,6 +131,7 @@ pub enum TokenKind {
|
||||||
Packed,
|
Packed,
|
||||||
True,
|
True,
|
||||||
False,
|
False,
|
||||||
|
Null,
|
||||||
Idk,
|
Idk,
|
||||||
|
|
||||||
Ctor,
|
Ctor,
|
||||||
|
@ -267,6 +268,7 @@ gen_token_kind! {
|
||||||
Packed = b"packed",
|
Packed = b"packed",
|
||||||
True = b"true",
|
True = b"true",
|
||||||
False = b"false",
|
False = b"false",
|
||||||
|
Null = b"null",
|
||||||
Idk = b"idk",
|
Idk = b"idk",
|
||||||
#[punkt]
|
#[punkt]
|
||||||
Ctor = ".{",
|
Ctor = ".{",
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue