ziglang / zig Goto Github PK
View Code? Open in Web Editor NEWGeneral-purpose programming language and toolchain for maintaining robust, optimal, and reusable software.
Home Page: https://ziglang.org
License: MIT License
General-purpose programming language and toolchain for maintaining robust, optimal, and reusable software.
Home Page: https://ziglang.org
License: MIT License
struct Foo {
field: i32,
}
fn func(f: Foo) {
f.field = 0; // should be an error
}
struct Aoeu {
field: i32,
field2: bool,
}
if guess < answer {
}
Parser thinks answer {
is a struct value expression.
Possible resolutions:
(
and )
in block expressionsstruct Foo {
field: i32,
}
fn f() {
const f : Foo = {.field = 1234,};
f.field = 0; // should be an error
}
Bare string literal: "example"
Type would be: [u8; 7]
No automatic null character.
Implicit automatic conversion to string
type, which is essentially a type def to:
struct string {
ptr: *const u8,
len: usize,
}
C string literal: c"example"
Type is: *const u8
Automatic null character.
As a litmus test, if you try to pass a string
to a C function, the param type would be *const u8
. This would be a type mismatch. If you pass a C string literal it would work fine.
There should be a way to perform basic arithmetic operations which can potentially overflow, such as addition, subtraction, and multiplication, and get the result as well as a boolean indicating whether it overflowed.
See for inspiration:
http://clang.llvm.org/docs/LanguageExtensions.html#checked-arithmetic-builtins
In debug mode, we might codegen this every time and do a panic if overflow occurs.
If I have the following string literals:
Since zig string literals have a length, we can make this only 1 global constant, and the shorter string literals can simply reference offsets of the larger one.
Also, mutable pointers by default. &const u8
or & u8
to declare a pointer type to u8.
So, delete mut
and let
keywords and add var
keyword.
%T
type%expr
to wrap expr in error type%%expr
prefix operator which is sugar for expr %% unreachable{}
.expr1 %% expr2
operator, where expr1 must be an error type. expr evaluates to unwrapped success value. expr2 must match or be unreachable. Alternate form: expr1 %% (err) => expr2
.%return expr
evaluates expr and returns if and only if expr evaluated to an error%void
codegens to a single integer, same as enum with all void fields.pub %.Foo;
to declare an error value.%return
in favor of just the %%
binary operator?
syntax for declaring a maybe type??
unwrapping expression?
qualifiers on a typethis returns the byte count of something known at compile time.
also think about getting the array length of static initialized arrays.
while condition {
continue;
break;
}
panic function prints a stack trace to stderr in debug mode; calls abort (after printing a message to stderr) in release mode.
Then make unreachable codegen to panic("unreachable") in debug mode, and to unreachable in release mode.
If any line in a block has indentation, then all lines in the block must have the same indentation.
Additionally, the indentation level of a block must be greater than or equal to indentation level of the parent block.
Sadly, the noreturn attribute according to libclang is an "unexposed attribute" which means we have to switch to the C++ API to gain support for it.
@shl_with_overflow
builtin fn#max_value(i32) + 1 // undefined behavior. -nuw +nsw
#max_value(u32) + 1 // undefined behavior. +nuw -nsw
#max_value(iw32) + 1 == #min_value(iw32) // -nuw -nsw
#max_value(uw32) + 1 == #min_value(uw32) // -nuw -nsw
#typeof()
on the declaration below#typeof()
for a parameter type#typeof()
loop#typeof()
on an imported symbolWe'll construct a dependency graph of every declaration with a type and then do the correct order.
export executable "hello";
use "std.zig";
export fn main(argc : isize, argv : *mut *mut u8, env : *mut *mut u8) -> i32 {
print_str("Hello, world!\n", (14 + 0 + 0) as isize);
return 0;
}
hello2.zig:6:42: error: invalid token: '+'
print_str("Hello, world!\n", (14 + 0 + 0) as isize);
^
void
(or left unspecified) codegen to a simple unsigned integer with the smallest bit width possible.#enum_count(...)
Foo.One { Point { .x = 1, .y = 2,} }
else
missing for integer types'a'...'z'
*
to get a pointer to the extra data attached (same as for loop)|x| expr
syntaxelse
missing when all integer types handledgoto has some requirements:
fn first(a : &u8) -> u8 {
a[0]
}
Currently all number literals are i32. Instead, have a number literal type which gets implicitly casted to the other numeric types.
use
to import
?so you can look at foo.ptr and foo.len in the debugger
operators &&=
and ||=
parse, but do not code gen.
a < b == c < d
should be parsed as (a < b) == (c < d)
.
This should be a compile error: a == b == c
also a != b != a
. Simply use parenthesis if you want this kind of thing.
Currently all string literals must be explicitly cast to a string to pass them to a function. Implicit casting should work.
#
functions into @
For example, if the user creates their own List struct, it would be nice if gdb knew about that and could represent it. Example: https://github.com/thejoshwolfe/legend-of-swarkland/blob/fc2947475b04f6d3de711b9040f61e79e06eda67/debug-scripts/list.py
It would be convenient if this could be integrated into zig somehow. zig could generate the .debug_gdb_scripts section: https://sourceware.org/gdb/onlinedocs/gdb/dotdebug_005fgdb_005fscripts-section.html
Maybe oop features are good for making GUIs. Implement a GUI with several types of widgets and investigate whether we need any OOP features.
test {
const p = &foo;
p();
}
inline fn foo() void {}
$ stage2/bin/zig test test3.zig
Global is external, but doesn't have external or weak linkage!
void ()* @test3.foo
Allowed, but p
is comptime pointer to a comptime-known function body. If var
is used instead of const
then it should be "error: pointer to inline function must be comptime-known"
jblow made a good point about this.
josh@jash:~/dev/zig$ mkdir build
josh@jash:~/dev/zig$ cd build
josh@jash:~/dev/zig/build$ cmake ..
-- The CXX compiler identification is GNU 5.2.1
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
Configuring zig version 0.0.0
-- Found LLVM: -lLLVMLTO -lLLVMObjCARCOpts -lLLVMLinker -lLLVMBitWriter -lLLVMIRReader -lLLVMBPFCodeGen -lLLVMBPFDesc -lLLVMBPFInfo -lLLVMBPFAsmPrinter -lLLVMAMDGPUCodeGen -lLLVMAMDGPUAsmParser -lLLVMAMDGPUUtils -lLLVMAMDGPUDesc -lLLVMAMDGPUInfo -lLLVMAMDGPUAsmPrinter -lLLVMSystemZDisassembler -lLLVMSystemZCodeGen -lLLVMSystemZAsmParser -lLLVMSystemZDesc -lLLVMSystemZInfo -lLLVMSystemZAsmPrinter -lLLVMHexagonDisassembler -lLLVMHexagonCodeGen -lLLVMHexagonDesc -lLLVMHexagonInfo -lLLVMNVPTXCodeGen -lLLVMNVPTXDesc -lLLVMNVPTXInfo -lLLVMNVPTXAsmPrinter -lLLVMCppBackendCodeGen -lLLVMCppBackendInfo -lLLVMMSP430CodeGen -lLLVMMSP430Desc -lLLVMMSP430Info -lLLVMMSP430AsmPrinter -lLLVMXCoreDisassembler -lLLVMXCoreCodeGen -lLLVMXCoreDesc -lLLVMXCoreInfo -lLLVMXCoreAsmPrinter -lLLVMMipsDisassembler -lLLVMMipsCodeGen -lLLVMMipsAsmParser -lLLVMMipsDesc -lLLVMMipsInfo -lLLVMMipsAsmPrinter -lLLVMAArch64Disassembler -lLLVMAArch64CodeGen -lLLVMAArch64AsmParser -lLLVMAArch64Desc -lLLVMAArch64Info -lLLVMAArch64AsmPrinter -lLLVMAArch64Utils -lLLVMARMDisassembler -lLLVMARMCodeGen -lLLVMARMAsmParser -lLLVMARMDesc -lLLVMARMInfo -lLLVMARMAsmPrinter -lLLVMPowerPCDisassembler -lLLVMPowerPCCodeGen -lLLVMPowerPCAsmParser -lLLVMPowerPCDesc -lLLVMPowerPCInfo -lLLVMPowerPCAsmPrinter -lLLVMSparcDisassembler -lLLVMSparcCodeGen -lLLVMSparcAsmParser -lLLVMSparcDesc -lLLVMSparcInfo -lLLVMSparcAsmPrinter -lLLVMMIRParser -lLLVMAsmParser -lLLVMLibDriver -lLLVMOption -lLLVMDebugInfoPDB -lLLVMTableGen -lLLVMOrcJIT -lLLVMLineEditor -lLLVMX86Disassembler -lLLVMX86AsmParser -lLLVMX86CodeGen -lLLVMSelectionDAG -lLLVMAsmPrinter -lLLVMX86Desc -lLLVMMCDisassembler -lLLVMX86Info -lLLVMX86AsmPrinter -lLLVMX86Utils -lLLVMMCJIT -lLLVMDebugInfoDWARF -lLLVMPasses -lLLVMipo -lLLVMVectorize -lLLVMInterpreter -lLLVMExecutionEngine -lLLVMRuntimeDyld -lLLVMCodeGen -lLLVMTarget -lLLVMScalarOpts -lLLVMProfileData -lLLVMObject -lLLVMMCParser -lLLVMBitReader -lLLVMInstCombine -lLLVMInstrumentation -lLLVMTransformUtils -lLLVMipa -lLLVMMC -lLLVMAnalysis -lLLVMCore -lLLVMSupport;-lz -lpthread -lffi -ledit -ltinfo -ldl -lm
-- Configuring done
-- Generating done
-- Build files have been written to: /home/josh/dev/zig/build
josh@jash:~/dev/zig/build$ make
Scanning dependencies of target run_tests
[ 7%] Building CXX object CMakeFiles/run_tests.dir/src/buffer.cpp.o
[ 15%] Building CXX object CMakeFiles/run_tests.dir/src/util.cpp.o
[ 23%] Building CXX object CMakeFiles/run_tests.dir/src/os.cpp.o
[ 30%] Building CXX object CMakeFiles/run_tests.dir/test/standalone.cpp.o
Linking CXX executable run_tests
[ 30%] Built target run_tests
Scanning dependencies of target zig
[ 38%] Building CXX object CMakeFiles/zig.dir/src/buffer.cpp.o
[ 46%] Building CXX object CMakeFiles/zig.dir/src/error.cpp.o
[ 53%] Building CXX object CMakeFiles/zig.dir/src/main.cpp.o
[ 61%] Building CXX object CMakeFiles/zig.dir/src/parser.cpp.o
[ 69%] Building CXX object CMakeFiles/zig.dir/src/tokenizer.cpp.o
[ 76%] Building CXX object CMakeFiles/zig.dir/src/util.cpp.o
[ 84%] Building CXX object CMakeFiles/zig.dir/src/codegen.cpp.o
[ 92%] Building CXX object CMakeFiles/zig.dir/src/zig_llvm.cpp.o
[100%] Building CXX object CMakeFiles/zig.dir/src/os.cpp.o
Linking CXX executable zig
[100%] Built target zig
josh@jash:~/dev/zig/build$ ./zig build --output hello ../test/hello.zig
Original source:
----------------
#link("c")
extern {
fn puts(s: *mut u8) -> i32;
fn exit(code: i32) -> unreachable;
}
fn _start() -> unreachable {
puts("Hello, world!");
exit(0);
}
Tokens:
---------
NumberSign #
Symbol link
LParen (
StringLiteral "c"
RParen )
Extern extern
LBrace {
Fn fn
Symbol puts
LParen (
Symbol s
Colon :
Star *
Mut mut
Symbol u8
RParen )
Arrow ->
Symbol i32
Semicolon ;
Fn fn
Symbol exit
LParen (
Symbol code
Colon :
Symbol i32
RParen )
Arrow ->
Unreachable unreachable
Semicolon ;
RBrace }
Fn fn
Symbol _start
LParen (
RParen )
Arrow ->
Unreachable unreachable
LBrace {
Symbol puts
LParen (
StringLiteral "Hello, world!"
RParen )
Semicolon ;
Symbol exit
LParen (
NumberLiteral 0
RParen )
Semicolon ;
RBrace }
EOF
AST:
------
Root
ExternBlock
FnDecl
FnProto 'puts'
ParamDecl 's'
'mut' PointerType
Type 'u8'
Type 'i32'
FnDecl
FnProto 'exit'
ParamDecl 'code'
Type 'i32'
Type 'unreachable'
FnDef
FnProto '_start'
Type 'unreachable'
Block
FnCallExpression
FnCall 'puts'
StringLiteralExpression 'Hello, world!'
FnCallExpression
FnCall 'exit'
NumberLiteralExpression 0
Semantic Analysis:
--------------------
OK
Code Generation:
------------------
; ModuleID = 'ZigModule'
@0 = private unnamed_addr constant [14 x i8] c"Hello, world!\00"
; Function Attrs: noreturn
declare void @exit(i32) #0
declare i32 @puts(i8*)
; Function Attrs: noreturn nounwind
define void @_start() #1 {
entry:
%0 = call i32 @puts(i8* getelementptr inbounds ([14 x i8], [14 x i8]* @0, i32 0, i32 0)), !dbg !8
call void @exit(i32 0), !dbg !10
unreachable, !dbg !10
}
attributes #0 = { noreturn }
attributes #1 = { noreturn nounwind }
!llvm.dbg.cu = !{!0}
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "zig 0.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: 1, enums: !2, subprograms: !3)
!1 = !DIFile(filename: "hello.zig", directory: "../test")
!2 = !{}
!3 = !{!4}
!4 = !DISubprogram(name: "_start", scope: !1, file: !1, line: 7, type: !5, isLocal: false, isDefinition: true, scopeLine: 7, isOptimized: false, function: void ()* @_start, variables: !2)
!5 = !DISubroutineType(types: !6)
!6 = !{!7}
!7 = !DIBasicType(name: "void", encoding: DW_ATE_unsigned)
!8 = !DILocation(line: 8, column: 5, scope: !9)
!9 = distinct !DILexicalBlock(scope: !4, file: !1, line: 7, column: 28)
!10 = !DILocation(line: 9, column: 5, scope: !9)
Link:
-------
OK
josh@jash:~/dev/zig/build$ ./hello
bash: ./hello: No such file or directory
The problem is that ./hello
is linked against /lib/ld64.so.1
instead of /lib64/ld-linux-x86-64.so.2
. This seems to be due to ld
being misconfigured on Debian.
This patch can work around the issue:
diff --git a/src/codegen.cpp b/src/codegen.cpp
index d59eff3..8318a43 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -721,6 +721,8 @@ void code_gen_link(CodeGen *g, const char *out_file) {
if (g->is_static) {
args.append("-static");
}
+ args.append("-dynamic-linker");
+ args.append("/lib64/ld-linux-x86-64.so.2");
args.append("-o");
args.append(out_file);
args.append((const char *)buf_ptr(&out_file_o));
jblow got it right
struct Foo {
field: i32,
}
fn f() {
const f : Foo = {.field = 1234,};
const p = &f.field; // should be an error
}
For example, we set size_in_bits on a bool to 1. But then later when making an array type we use this value and multiply by the array size. Is that right?
On structs when making the member debug type we set the alignment of members and calculate the offset in bits to each member. Are we doing it right?
We also set the alignment for structs and have the option to set alignment on local variables and parameters, and more.
Related, figure out exactly what is the difference between packed structs and normal structs. Will LLVM re-order fields to improve alignment? Or is that our job? If LLVM does it, how do we know which values to give to the debug info? If we do it then we need to add that to codegen.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.