mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Updated grammar. Removal of elif. Removal of ':' ';' in some ct statements. Empty faults is now an error. Remove "define" for types. Remove "private". Better errors on incorrect bitstruct syntax. Introduction of wildcard type rather than optional wildcard. Removal of scaled vector type. mkdir and rmdir. Disallow define @Foo() = { @inline }. Add handling for @optreturn and change it to @return!. Restrict interface style functions. Updated x64 ABI. stdlib updates to string. Removed deprecated functions. Update how variadics are implemented. Extended error messages. x86 ABI fixes. Shift check fixes. '!' and '?' are flipped. No trailing ',' allowed in functions. Fix to string parsing. Allow l suffix. Simplifying flatpath. any replaces variant, anyfault replaces anyerr. Allow getting the underlying type of anyfault. De-duplicate string constants. Fix of readme. Extended list. Fix of "(MyEnum)x + 1". Clock and DateTime types. Fixes to array concat.
This commit is contained in:
committed by
Christoffer Lerno
parent
d14e778232
commit
809321e20c
@@ -89,7 +89,7 @@ fn int! decode(String in, char* out, int* invalid_char_index = null)
|
||||
if (c == ERR)
|
||||
{
|
||||
if (invalid_char_index) *invalid_char_index = i;
|
||||
return DecodingError.INVALID_CHARACTER!;
|
||||
return DecodingError.INVALID_CHARACTER?;
|
||||
}
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@ fn void! main()
|
||||
printf("Result: %s\n", &buffer);
|
||||
char *to_decode = "aGVsbG8gd29ybGRcMA==";
|
||||
char[*] result = b64"aGVsbG8gd29ybGRcMA==";
|
||||
decode((String)to_decode[0..19], &buffer)?;
|
||||
decode((String)to_decode[0..19], &buffer)!;
|
||||
printf("Result: %s\n", &buffer);
|
||||
printf("Result direct: %.*s\n", 13, &result);
|
||||
}
|
||||
@@ -12,7 +12,7 @@ fault InterpretError
|
||||
fn void! print_error(usz pos, String err)
|
||||
{
|
||||
io::printfn("Error at %s: %s", pos, err);
|
||||
return InterpretError.INTEPRET_FAILED!;
|
||||
return InterpretError.INTEPRET_FAILED?;
|
||||
}
|
||||
|
||||
fn void! brainf(String program)
|
||||
@@ -81,5 +81,5 @@ fn void! main()
|
||||
>>>+[[-]++++++>>>]<<<[[<++++++++<++>>-]+<.<[>----<-]<]
|
||||
<<[>>>>>[>>>[-]+++++++++<[>-<-]+++++++++>[-[<->-]+[<<<]]<[>+<-]>]<<-]<<-
|
||||
]`;
|
||||
brainf(program)?;
|
||||
brainf(program)!;
|
||||
}
|
||||
@@ -3,11 +3,11 @@ import libc;
|
||||
import std::io;
|
||||
|
||||
struct Doc { Head *head; }
|
||||
struct Head { VarString* title; }
|
||||
struct Head { DString* title; }
|
||||
|
||||
struct Summary
|
||||
{
|
||||
VarString* title;
|
||||
DString* title;
|
||||
bool ok;
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ fn bool contains(String haystack, String needle)
|
||||
|
||||
macro @dupe(value)
|
||||
{
|
||||
$typeof(&value) temp = malloc_checked($typeof(value))?;
|
||||
$typeof(&value) temp = malloc_checked($typeof(value))!;
|
||||
*temp = value;
|
||||
return temp;
|
||||
}
|
||||
@@ -56,11 +56,11 @@ fault ReadError
|
||||
|
||||
fn Doc! readDoc(String url)
|
||||
{
|
||||
if (contains(url, "fail")) return ReadError.BAD_READ!;
|
||||
if (contains(url, "fail")) return ReadError.BAD_READ?;
|
||||
if (contains(url, "head-missing")) return { .head = null };
|
||||
if (contains(url, "title-missing")) return { @dupe(Head { .title = null }) };
|
||||
if (contains(url, "title-empty")) return { @dupe(Head { .title = @dupe((VarString)null) }) };
|
||||
VarString str;
|
||||
if (contains(url, "title-empty")) return { @dupe(Head { .title = @dupe((DString)null) }) };
|
||||
DString str;
|
||||
str.printf("Title of %s", url);
|
||||
return { @dupe(Head { .title = @dupe(str) }) };
|
||||
}
|
||||
@@ -96,9 +96,9 @@ fault TitleResult
|
||||
|
||||
fn bool! isTitleNonEmpty(Doc doc)
|
||||
{
|
||||
if (!doc.head) return TitleResult.TITLE_MISSING!;
|
||||
VarString* head = doc.head.title;
|
||||
if (!head) return TitleResult.TITLE_MISSING!;
|
||||
if (!doc.head) return TitleResult.TITLE_MISSING?;
|
||||
DString* head = doc.head.title;
|
||||
if (!head) return TitleResult.TITLE_MISSING?;
|
||||
return head.len() > 0;
|
||||
}
|
||||
|
||||
@@ -133,7 +133,7 @@ fn void main()
|
||||
bool! has_title = readWhetherTitleNonEmpty(url);
|
||||
// This looks a bit less than elegant, but as you see it's mostly due to having to
|
||||
// use printf here.
|
||||
io::printf(" Has title: %s vs %s\n", bool_to_string(has_title) ?? (catch? has_title).nameof, has_title ?? false);
|
||||
io::printf(" Has title: %s vs %s\n", bool_to_string(has_title) ?? (@catchof(has_title)).nameof, has_title ?? false);
|
||||
};
|
||||
dynamic_arena.reset();
|
||||
}
|
||||
|
||||
52
resources/examples/contextfree/cleanup.c3
Normal file
52
resources/examples/contextfree/cleanup.c3
Normal file
@@ -0,0 +1,52 @@
|
||||
import std::io;
|
||||
|
||||
|
||||
struct Resource
|
||||
{
|
||||
String name;
|
||||
}
|
||||
|
||||
fault Error
|
||||
{
|
||||
WELCOME_TO_YOUR_DOOM
|
||||
}
|
||||
|
||||
fn Resource! resource_init(String name)
|
||||
{
|
||||
io::printfn("open %s", name);
|
||||
return { name };
|
||||
}
|
||||
|
||||
fn void Resource.deinit(Resource this) => io::printfn("close %s", this.name);
|
||||
|
||||
macro void! @open_with(String name; @body(Resource resource))
|
||||
{
|
||||
Resource resource = resource_init(name)!;
|
||||
defer {
|
||||
io::printn("Using open_with to close");
|
||||
resource.deinit();
|
||||
}
|
||||
@body(resource);
|
||||
}
|
||||
|
||||
fn Resource! prep_out(String out_name, String[] prep_names)
|
||||
{
|
||||
Resource writer = resource_init(out_name)!; // Rethrow the optional result
|
||||
defer catch writer.deinit();
|
||||
foreach (name : prep_names)
|
||||
{
|
||||
@open_with(name; Resource reader)
|
||||
{
|
||||
io::printfn("use %s", reader.name);
|
||||
// if (true) return Error.WELCOME_TO_YOUR_DOOM?;
|
||||
}!;
|
||||
}
|
||||
return writer;
|
||||
}
|
||||
|
||||
fn void! main()
|
||||
{
|
||||
Resource writer = prep_out("out", String[] { "a", "b"})!;
|
||||
defer writer.deinit();
|
||||
io::printn("use out");
|
||||
}
|
||||
@@ -23,10 +23,10 @@ int err_count = 0;
|
||||
fn int! askGuess(int high)
|
||||
{
|
||||
libc::printf("Guess a number between 1 and %d: ", high);
|
||||
String text = readLine()?;
|
||||
String text = readLine()!;
|
||||
char* end = null;
|
||||
int value = (int)libc::strtol(text.ptr, &end, 10);
|
||||
if (end && end[0] >= ' ') return InputResult.NOT_AN_INT!;
|
||||
if (end && end[0] >= ' ') return InputResult.NOT_AN_INT?;
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ fn String! readLine()
|
||||
{
|
||||
char* chars = tmalloc(1024);
|
||||
isz loaded = getline(&chars, &&(usz)1023, libc::stdin());
|
||||
if (loaded < 0) return InputResult.FAILED_TO_READ!;
|
||||
if (loaded < 0) return InputResult.FAILED_TO_READ?;
|
||||
chars[loaded] = 0;
|
||||
return (String)chars[0..(loaded - 1)];
|
||||
}
|
||||
@@ -44,7 +44,7 @@ fn int! askGuessMulti(int high)
|
||||
while (true)
|
||||
{
|
||||
int! result = askGuess(high);
|
||||
if (catch? result == InputResult.NOT_AN_INT)
|
||||
if (@catchof(result) == InputResult.NOT_AN_INT)
|
||||
{
|
||||
libc::printf("I didn't understand that.\n");
|
||||
err_count++;
|
||||
@@ -59,7 +59,7 @@ fn void! Game.play(Game *game)
|
||||
{
|
||||
while (!game.done)
|
||||
{
|
||||
int guess = askGuessMulti(game.high)?;
|
||||
int guess = askGuessMulti(game.high)!;
|
||||
game.report(guess);
|
||||
game.update(guess);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ module load_world;
|
||||
import std::io;
|
||||
fn void! main()
|
||||
{
|
||||
File f = file::open("examples/hello_world.txt", "rb")?;
|
||||
File f = file::open("examples/hello_world.txt", "rb")!;
|
||||
defer f.close()!!;
|
||||
while (!f.eof())
|
||||
{
|
||||
|
||||
@@ -35,17 +35,17 @@ fn void Map.init(Map *map, uint capacity = 128)
|
||||
|
||||
fn Type! Map.valueForKey(Map *map, Key key)
|
||||
{
|
||||
if (!map.map) return MapResult.KEY_NOT_FOUND!;
|
||||
if (!map.map) return MapResult.KEY_NOT_FOUND?;
|
||||
uint hash = key.hash();
|
||||
usz pos = hash & map.mod;
|
||||
Entry* entry = &map.map[pos];
|
||||
if (!entry) return MapResult.KEY_NOT_FOUND!;
|
||||
if (!entry) return MapResult.KEY_NOT_FOUND?;
|
||||
while (entry)
|
||||
{
|
||||
if (entry.hash == hash && entry.key == key) return entry.value;
|
||||
entry = entry.next;
|
||||
}
|
||||
return MapResult.KEY_NOT_FOUND!;
|
||||
return MapResult.KEY_NOT_FOUND?;
|
||||
}
|
||||
|
||||
fn Type! Map.set(Map *map, Key key, Type value) @maydiscard
|
||||
@@ -67,7 +67,7 @@ fn Type! Map.set(Map *map, Key key, Type value) @maydiscard
|
||||
entry.value = value;
|
||||
entry.hash = hash;
|
||||
entry.key = key;
|
||||
return MapResult.KEY_NOT_FOUND!;
|
||||
return MapResult.KEY_NOT_FOUND?;
|
||||
}
|
||||
if (entry.hash == hash && entry.key == key)
|
||||
{
|
||||
@@ -87,7 +87,7 @@ fn Type! Map.set(Map *map, Key key, Type value) @maydiscard
|
||||
new.next = null;
|
||||
new.used = true;
|
||||
entry.next = new;
|
||||
return MapResult.KEY_NOT_FOUND!;
|
||||
return MapResult.KEY_NOT_FOUND?;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -144,7 +144,7 @@ fn void scale_bodies(Planet[] bodies, double scale)
|
||||
|
||||
fn void main(String[] args)
|
||||
{
|
||||
int n = args.len < 2 ? 50000000 : str::to_int(args[1])!!;
|
||||
int n = args.len < 2 ? 50000000 : args[1].to_int()!!;
|
||||
|
||||
Planet[] bodies = &planet_bodies;
|
||||
offset_momentum(bodies);
|
||||
|
||||
@@ -13,9 +13,9 @@ fault TokenResult
|
||||
fn void main(String[] args)
|
||||
{
|
||||
// Grab a string from stdin
|
||||
VarString s = io::stdin().getline();
|
||||
DString s = io::stdin().getline();
|
||||
// Delete it at scope end [defer]
|
||||
defer s.destroy();
|
||||
defer s.free();
|
||||
|
||||
// Grab the string as a slice.
|
||||
String numbers = s.str();
|
||||
@@ -77,8 +77,8 @@ fn String! read_next(String* remaining)
|
||||
}
|
||||
|
||||
// If it's a zero length token, return an optional result.
|
||||
if (!len) return TokenResult.NO_MORE_TOKENS!;
|
||||
if (!len) return TokenResult.NO_MORE_TOKENS?;
|
||||
|
||||
// Otherwise create a slice from the pointer start and length.
|
||||
return ptr_start[:len];
|
||||
return (String)ptr_start[:len];
|
||||
}
|
||||
|
||||
@@ -9,14 +9,14 @@ fault TestErr
|
||||
fn int! eventually_succeed()
|
||||
{
|
||||
static int i = 0;
|
||||
if (i++ < 3) return TestErr.NOPE!;
|
||||
if (i++ < 3) return TestErr.NOPE?;
|
||||
return i * 3;
|
||||
}
|
||||
|
||||
macro @retry(#function, int retries = 3)
|
||||
{
|
||||
var $Type = $typeof(#function);
|
||||
anyerr e;
|
||||
anyfault e;
|
||||
do
|
||||
{
|
||||
$Type! result = #function;
|
||||
|
||||
@@ -43,7 +43,7 @@ fn void eval_AtA_times_u(double[] u, double[] atau, double[] x)
|
||||
|
||||
fn void main(String[] args)
|
||||
{
|
||||
int n = args.len == 2 ? str::to_int(args[1])!! : 2000;
|
||||
int n = args.len == 2 ? args[1].to_int()!! : 2000;
|
||||
temparr = malloc(double, n);
|
||||
double[] u = malloc(double, n);
|
||||
double[] v = malloc(double, n);
|
||||
|
||||
17
resources/examples/time.c3
Normal file
17
resources/examples/time.c3
Normal file
@@ -0,0 +1,17 @@
|
||||
import std::io;
|
||||
import std::time;
|
||||
import std::math;
|
||||
|
||||
fn void main()
|
||||
{
|
||||
Clock start = clock::now();
|
||||
DateTime d = datetime::now();
|
||||
io::printfn("Today is: %d-%02d-%02d %02d:%02d", d.year, d.month.ordinal + 1, d.day, d.hour, d.min);
|
||||
io::printfn("Epoch timestamp: %d", d.time / 1_000);
|
||||
TzDateTime td = d.to_local();
|
||||
int absolute_offset = math::abs(td.gmt_offset);
|
||||
int offset_hour = absolute_offset / 3600;
|
||||
int offset_min = (absolute_offset / 60) % 60;
|
||||
io::printfn("Local time is: %d-%02d-%02d %02d:%02d:%02d %c%02d:%02d", td.year, td.month.ordinal + 1, td.day, td.hour, td.min, td.sec, td.gmt_offset < 0 ? '-' : '+', offset_hour, offset_min);
|
||||
io::printfn("Executed the above in %d ns", start.to_now());
|
||||
}
|
||||
Reference in New Issue
Block a user