mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
implement %% prefix operator
See #23 also make undefined constants use llvm undef value
This commit is contained in:
parent
c0dc0ca6c9
commit
deb3586884
9 changed files with 54 additions and 20 deletions
|
|
@ -48,8 +48,8 @@ compromises backward compatibility.
|
||||||
### Current Status
|
### Current Status
|
||||||
|
|
||||||
* Have a look in the example/ folder to see some code examples.
|
* Have a look in the example/ folder to see some code examples.
|
||||||
* Basic language features available such as loops, inline assembly,
|
* Most language features are available, but many edge cases and errors are
|
||||||
expressions, literals, functions, importing, structs, tagged unions.
|
not yet implemented.
|
||||||
* Linux x86_64 is supported.
|
* Linux x86_64 is supported.
|
||||||
* Building for the native target is supported.
|
* Building for the native target is supported.
|
||||||
* Optimized machine code that Zig produces is indistinguishable from
|
* Optimized machine code that Zig produces is indistinguishable from
|
||||||
|
|
|
||||||
|
|
@ -137,7 +137,7 @@ ContainerInitBody : list(StructLiteralField, ",") | list(Expression, ",")
|
||||||
|
|
||||||
StructLiteralField : "." "Symbol" "=" Expression
|
StructLiteralField : "." "Symbol" "=" Expression
|
||||||
|
|
||||||
PrefixOp : "!" | "-" | "~" | "*" | ("&" option("const")) | "?" | "%"
|
PrefixOp : "!" | "-" | "~" | "*" | ("&" option("const")) | "?" | "%" | "%%"
|
||||||
|
|
||||||
PrimaryExpression : "Number" | "String" | "CharLiteral" | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | "Symbol" | ("@" "Symbol" FnCallExpression) | ArrayType | AsmExpression | ("error" "." "Symbol")
|
PrimaryExpression : "Number" | "String" | "CharLiteral" | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | "Symbol" | ("@" "Symbol" FnCallExpression) | ArrayType | AsmExpression | ("error" "." "Symbol")
|
||||||
|
|
||||||
|
|
@ -154,7 +154,7 @@ KeywordLiteral : "true" | "false" | "null" | "break" | "continue" | "undefined"
|
||||||
|
|
||||||
```
|
```
|
||||||
x() x[] x.y
|
x() x[] x.y
|
||||||
!x -x ~x *x &x ?x %x
|
!x -x ~x *x &x ?x %x %%x
|
||||||
x{}
|
x{}
|
||||||
* / %
|
* / %
|
||||||
+ -
|
+ -
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ import "std.zig";
|
||||||
// Things to do to make this work:
|
// Things to do to make this work:
|
||||||
// * var args printing
|
// * var args printing
|
||||||
// * defer
|
// * defer
|
||||||
// * %% binary operator
|
|
||||||
// * %% prefix operator
|
// * %% prefix operator
|
||||||
// * cast err type to string
|
// * cast err type to string
|
||||||
// * string equality
|
// * string equality
|
||||||
|
|
@ -21,7 +20,7 @@ pub fn main(args: [][]u8) %void => {
|
||||||
return usage(exe);
|
return usage(exe);
|
||||||
} else {
|
} else {
|
||||||
var is: InputStream;
|
var is: InputStream;
|
||||||
is.open(arg, OpenReadOnly) %% (err) => {
|
is.open(arg, OpenReadOnly) %% |err| {
|
||||||
%%stderr.print("Unable to open file: {}", ([]u8])(err));
|
%%stderr.print("Unable to open file: {}", ([]u8])(err));
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
@ -45,7 +44,7 @@ fn cat_stream(is: InputStream) %void => {
|
||||||
var buf: [1024 * 4]u8;
|
var buf: [1024 * 4]u8;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
const bytes_read = is.read(buf) %% (err) => {
|
const bytes_read = is.read(buf) %% |err| {
|
||||||
%%stderr.print("Unable to read from stream: {}", ([]u8)(err));
|
%%stderr.print("Unable to read from stream: {}", ([]u8)(err));
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
@ -54,7 +53,7 @@ fn cat_stream(is: InputStream) %void => {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
stdout.write(buf[0...bytes_read]) %% (err) => {
|
stdout.write(buf[0...bytes_read]) %% |err| {
|
||||||
%%stderr.print("Unable to write to stdout: {}", ([]u8)(err));
|
%%stderr.print("Unable to write to stdout: {}", ([]u8)(err));
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,35 +4,35 @@ import "std.zig";
|
||||||
import "rand.zig";
|
import "rand.zig";
|
||||||
|
|
||||||
pub fn main(args: [][]u8) %void => {
|
pub fn main(args: [][]u8) %void => {
|
||||||
stderr.print_str("Welcome to the Guess Number Game in Zig.\n");
|
%%stderr.print_str("Welcome to the Guess Number Game in Zig.\n");
|
||||||
|
|
||||||
var seed : u32;
|
var seed : u32;
|
||||||
const seed_bytes = (&u8)(&seed)[0...4];
|
const seed_bytes = (&u8)(&seed)[0...4];
|
||||||
os_get_random_bytes(seed_bytes) %% unreachable{};
|
%%os_get_random_bytes(seed_bytes);
|
||||||
|
|
||||||
var rand = rand_new(seed);
|
var rand = rand_new(seed);
|
||||||
|
|
||||||
const answer = rand.range_u64(0, 100) + 1;
|
const answer = rand.range_u64(0, 100) + 1;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
stderr.print_str("\nGuess a number between 1 and 100: ");
|
%%stderr.print_str("\nGuess a number between 1 and 100: ");
|
||||||
var line_buf : [20]u8;
|
var line_buf : [20]u8;
|
||||||
|
|
||||||
const line_len = stdin.read(line_buf) %% |err| {
|
const line_len = stdin.read(line_buf) %% |err| {
|
||||||
stderr.print_str("Unable to read from stdin.\n");
|
%%stderr.print_str("Unable to read from stdin.\n");
|
||||||
return err;
|
return err;
|
||||||
};
|
};
|
||||||
|
|
||||||
const guess = parse_u64(line_buf[0...line_len - 1], 10) %% {
|
const guess = parse_u64(line_buf[0...line_len - 1], 10) %% {
|
||||||
stderr.print_str("Invalid number.\n");
|
%%stderr.print_str("Invalid number.\n");
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
if (guess > answer) {
|
if (guess > answer) {
|
||||||
stderr.print_str("Guess lower.\n");
|
%%stderr.print_str("Guess lower.\n");
|
||||||
} else if (guess < answer) {
|
} else if (guess < answer) {
|
||||||
stderr.print_str("Guess higher.\n");
|
%%stderr.print_str("Guess higher.\n");
|
||||||
} else {
|
} else {
|
||||||
stderr.print_str("You win!\n");
|
%%stderr.print_str("You win!\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -405,6 +405,7 @@ enum PrefixOp {
|
||||||
PrefixOpDereference,
|
PrefixOpDereference,
|
||||||
PrefixOpMaybe,
|
PrefixOpMaybe,
|
||||||
PrefixOpError,
|
PrefixOpError,
|
||||||
|
PrefixOpUnwrapError,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AstNodePrefixOpExpr {
|
struct AstNodePrefixOpExpr {
|
||||||
|
|
|
||||||
|
|
@ -3656,6 +3656,20 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
case PrefixOpUnwrapError:
|
||||||
|
{
|
||||||
|
TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, expr_node);
|
||||||
|
|
||||||
|
if (type_entry->id == TypeTableEntryIdInvalid) {
|
||||||
|
return type_entry;
|
||||||
|
} else if (type_entry->id == TypeTableEntryIdErrorUnion) {
|
||||||
|
return type_entry->data.error.child_type;
|
||||||
|
} else {
|
||||||
|
add_node_error(g, expr_node,
|
||||||
|
buf_sprintf("expected error type, got '%s'", buf_ptr(&type_entry->name)));
|
||||||
|
return g->builtin_types.entry_invalid;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -833,6 +833,24 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {
|
||||||
{
|
{
|
||||||
zig_panic("TODO codegen PrefixOpError");
|
zig_panic("TODO codegen PrefixOpError");
|
||||||
}
|
}
|
||||||
|
case PrefixOpUnwrapError:
|
||||||
|
{
|
||||||
|
LLVMValueRef expr_val = gen_expr(g, expr_node);
|
||||||
|
TypeTableEntry *expr_type = get_expr_type(expr_node);
|
||||||
|
assert(expr_type->id == TypeTableEntryIdErrorUnion);
|
||||||
|
TypeTableEntry *child_type = expr_type->data.error.child_type;
|
||||||
|
// TODO in debug mode, put a panic here if the error is not 0
|
||||||
|
if (child_type->size_in_bits > 0) {
|
||||||
|
LLVMValueRef child_val_ptr = LLVMBuildStructGEP(g->builder, expr_val, 1, "");
|
||||||
|
if (handle_is_ptr(child_type)) {
|
||||||
|
return child_val_ptr;
|
||||||
|
} else {
|
||||||
|
return expr_val;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
|
|
@ -2219,7 +2237,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
|
||||||
assert(const_val->ok);
|
assert(const_val->ok);
|
||||||
|
|
||||||
if (const_val->undef) {
|
if (const_val->undef) {
|
||||||
return LLVMConstNull(type_entry->type_ref);
|
return LLVMGetUndef(type_entry->type_ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type_entry->id == TypeTableEntryIdInt) {
|
if (type_entry->id == TypeTableEntryIdInt) {
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,7 @@ static const char *prefix_op_str(PrefixOp prefix_op) {
|
||||||
case PrefixOpDereference: return "*";
|
case PrefixOpDereference: return "*";
|
||||||
case PrefixOpMaybe: return "?";
|
case PrefixOpMaybe: return "?";
|
||||||
case PrefixOpError: return "%";
|
case PrefixOpError: return "%";
|
||||||
|
case PrefixOpUnwrapError: return "%%";
|
||||||
}
|
}
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
|
|
@ -1664,6 +1665,7 @@ static PrefixOp tok_to_prefix_op(Token *token) {
|
||||||
case TokenIdStar: return PrefixOpDereference;
|
case TokenIdStar: return PrefixOpDereference;
|
||||||
case TokenIdMaybe: return PrefixOpMaybe;
|
case TokenIdMaybe: return PrefixOpMaybe;
|
||||||
case TokenIdPercent: return PrefixOpError;
|
case TokenIdPercent: return PrefixOpError;
|
||||||
|
case TokenIdPercentPercent: return PrefixOpUnwrapError;
|
||||||
case TokenIdBoolAnd: return PrefixOpAddressOf;
|
case TokenIdBoolAnd: return PrefixOpAddressOf;
|
||||||
default: return PrefixOpInvalid;
|
default: return PrefixOpInvalid;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,9 @@ import "syscall.zig";
|
||||||
// The compiler treats this file special by implicitly importing the function `main`
|
// The compiler treats this file special by implicitly importing the function `main`
|
||||||
// from the root source file.
|
// from the root source file.
|
||||||
|
|
||||||
var argc: isize;
|
var argc: isize = undefined;
|
||||||
var argv: &&u8;
|
var argv: &&u8 = undefined;
|
||||||
var env: &&u8;
|
var env: &&u8 = undefined;
|
||||||
|
|
||||||
#attribute("naked")
|
#attribute("naked")
|
||||||
export fn _start() unreachable => {
|
export fn _start() unreachable => {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue