mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Fix stack setting after error return. Some fixes to examples.
This commit is contained in:
committed by
Christoffer Lerno
parent
b1d83e2ccd
commit
bb28f6e61c
@@ -43,8 +43,9 @@ fn String new(char[] c)
|
||||
|
||||
fn ZString String.zstr(String* str)
|
||||
{
|
||||
StringData* data = str.data();
|
||||
if (!str) return (ZString)"";
|
||||
StringData* data = str.data();
|
||||
if (!data) return (ZString)"";
|
||||
if (data.capacity == data.len)
|
||||
{
|
||||
libc::printf("feofk\n");
|
||||
@@ -63,6 +64,7 @@ fn usize String.len(String* this)
|
||||
if (!*this) return 0;
|
||||
return this.data().len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @require new_size <= this.len()
|
||||
*/
|
||||
@@ -87,6 +89,25 @@ fn void String.append_utf32(String* str, Char32[] chars)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @require index < str.len()
|
||||
**/
|
||||
fn void String.set(String* str, usize index, char c)
|
||||
{
|
||||
str.data().chars[index] = c;
|
||||
}
|
||||
|
||||
fn void String.append_repeat(String* str, char c, usize times)
|
||||
{
|
||||
if (times == 0) return;
|
||||
str.reserve(times);
|
||||
StringData* data = str.data();
|
||||
for (usize i = 0; i < times; i++)
|
||||
{
|
||||
data.chars[data.len++] = c;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @require c < 0x10ffff
|
||||
*/
|
||||
@@ -174,6 +195,7 @@ fn void String.destroy(String* str)
|
||||
{
|
||||
if (!*str) return;
|
||||
StringData* data = str.data();
|
||||
if (!data) return;
|
||||
data.allocator.free(data);
|
||||
*str = (String)null;
|
||||
}
|
||||
|
||||
25
resources/examples/binarydigits.c3
Normal file
25
resources/examples/binarydigits.c3
Normal file
@@ -0,0 +1,25 @@
|
||||
module binarydigits;
|
||||
import std::math;
|
||||
import libc;
|
||||
fn void main()
|
||||
{
|
||||
for (int i = 0; i < 20; i++)
|
||||
{
|
||||
String s = bin(i);
|
||||
defer s.destroy();
|
||||
libc::printf("%s\n", s.zstr());
|
||||
}
|
||||
}
|
||||
|
||||
fn String bin(int x)
|
||||
{
|
||||
int bits = 1 + (int)(x == 0 ? 0 : math::log10((double)(x)) / math::log10(2));
|
||||
String str;
|
||||
str.append_repeat('0', bits);
|
||||
for (int i = 0; i < bits; i++)
|
||||
{
|
||||
str.set((usize)(bits - i - 1), x & 1 ? '1' : '0');
|
||||
x >>= 1;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
module guess_number;
|
||||
import std::mem;
|
||||
import std::io;
|
||||
import libc;
|
||||
|
||||
@@ -34,7 +33,7 @@ fn int! askGuess(int high)
|
||||
fn char[]! readLine()
|
||||
{
|
||||
char* chars = mem::talloc(1024)?;
|
||||
isize loaded = getline(&chars, &&(usize)1023, 2libc::stdin());
|
||||
isize loaded = getline(&chars, &&(usize)1023, libc::stdin());
|
||||
if (loaded < 0) return InputResult.FAILED_TO_READ!;
|
||||
chars[loaded] = 0;
|
||||
return chars[0..(loaded - 1)];
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
module binarydigits;
|
||||
|
||||
fn int main()
|
||||
{
|
||||
fot (int i = 0; i < 20; i++)
|
||||
{
|
||||
printf("%s\n", bin(i));
|
||||
}
|
||||
}
|
||||
|
||||
fn string bin(int x)
|
||||
{
|
||||
int bits = (x == 0) ? 1 : log10((double)(x)) / log10(2);
|
||||
string ret = str.make_repeat('0' as bits);
|
||||
for (int i = 0; i < bits; i++)
|
||||
{
|
||||
ret[bits - i - 1] = x & 1 ? '1' : '0';
|
||||
x >>= 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -1,9 +1,14 @@
|
||||
module map(Key, Type);
|
||||
module std::container::map <Key, Type>;
|
||||
|
||||
fault MapResult
|
||||
{
|
||||
KEY_NOT_FOUND
|
||||
}
|
||||
|
||||
public struct Entry
|
||||
{
|
||||
Key key;
|
||||
Type* value;
|
||||
Type value;
|
||||
usize hash;
|
||||
Entry* next;
|
||||
}
|
||||
@@ -13,34 +18,37 @@ public struct Map
|
||||
usize size;
|
||||
void* map;
|
||||
uint mod;
|
||||
Allocator allocator;
|
||||
}
|
||||
|
||||
public fn Map* Map.init(Map *map)
|
||||
/**
|
||||
* @require map != null
|
||||
**/
|
||||
public fn void Map.init(Map *map, Allocator allocator)
|
||||
{
|
||||
*map = { };
|
||||
return map;
|
||||
map.allocator = allocator;
|
||||
}
|
||||
|
||||
public fn Type* Map.valueForKey(Map *map, Key key)
|
||||
public fn Type! Map.valueForKey(Map *map, Key key)
|
||||
{
|
||||
if (!map.map) return nil;
|
||||
if (!map.map) return null;
|
||||
usize hash = key.hash();
|
||||
usize pos = hash & map.mod;
|
||||
Entry* entry = &map.map[pop];
|
||||
if () return nil;
|
||||
if (!entry) return MapResult.KEY_NOT_FOUND!;
|
||||
while (entry)
|
||||
{
|
||||
if (entry.hash == hash && entry.key == key) return entry.value;
|
||||
entry = entry.next;
|
||||
}
|
||||
return nil;
|
||||
return MapResult.KEY_NOT_FOUND!;
|
||||
}
|
||||
|
||||
public fn Type *Map.setValueForKey(Map *map, Key key, Type *value)
|
||||
public fn Type *Map.set(Map *map, Key key, Type value)
|
||||
{
|
||||
if (!map.map)
|
||||
{
|
||||
map.map = @calloc(Entry, 16);
|
||||
map.map = allocator.calloc(Entry, 16);
|
||||
map.mod = 0x0F;
|
||||
}
|
||||
|
||||
@@ -66,42 +74,14 @@ public fn Type *Map.setValueForKey(Map *map, Key key, Type *value)
|
||||
{
|
||||
entry = entry.next;
|
||||
}
|
||||
entry.next = @malloc(Entry);
|
||||
entry.next = allocator.alloc(Entry);
|
||||
entry = entry.next;
|
||||
}
|
||||
}
|
||||
|
||||
public fn usize Map.size(Vector *vector)
|
||||
public fn usize Map.size(Map* map)
|
||||
{
|
||||
return vector.array.size;
|
||||
return map.size;
|
||||
}
|
||||
|
||||
public fn void Map.removeLast(Vector *vector)
|
||||
{
|
||||
vector.array.pop();
|
||||
}
|
||||
|
||||
public macro Vector.foreach(Vector *vector, macro void(Type value) body)
|
||||
{
|
||||
for (usize i = 0, i < vector.array.size; i++)
|
||||
{
|
||||
@body(vector.array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
test
|
||||
{
|
||||
define IntVector = Vector(int);
|
||||
IntVector vector = vector.init();
|
||||
vector.add(1);
|
||||
vector.add(2);
|
||||
for (int i : vector)
|
||||
{
|
||||
printDigit(i);
|
||||
}
|
||||
@vector.foreach(int i)
|
||||
{
|
||||
printDigit(i);
|
||||
}
|
||||
vector.destroy();
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
module test;
|
||||
|
||||
|
||||
public macro retry(#function, int retries = 3)
|
||||
{
|
||||
error e;
|
||||
while (1)
|
||||
{
|
||||
auto! result = #function;
|
||||
try (result) return result;
|
||||
catch (e = result);
|
||||
} while (retries-- > 0)
|
||||
return e!;
|
||||
}
|
||||
|
||||
fn void main()
|
||||
{
|
||||
int! result = @retry(eventually_succeed());
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
public test;
|
||||
|
||||
/**
|
||||
* @require parse(a = b), parse(b = a)
|
||||
*/
|
||||
public macro void swap(&a, &b)
|
||||
{
|
||||
typeof(a) temp = a;
|
||||
a = b;
|
||||
b = temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @require parse(a = b), parse(b = a)
|
||||
*/
|
||||
public macro void swap2(auto &a, auto &b)
|
||||
{
|
||||
auto temp = a;
|
||||
a = b;
|
||||
b = temp;
|
||||
}
|
||||
44
resources/examples/retry.c3
Normal file
44
resources/examples/retry.c3
Normal file
@@ -0,0 +1,44 @@
|
||||
module test;
|
||||
import libc;
|
||||
|
||||
fault TestErr
|
||||
{
|
||||
NOPE
|
||||
}
|
||||
|
||||
fn int! eventually_succeed()
|
||||
{
|
||||
static int i = 0;
|
||||
if (i++ < 3) return TestErr.NOPE!;
|
||||
return i * 3;
|
||||
}
|
||||
|
||||
macro @retry(#function, int retries = 3)
|
||||
{
|
||||
var $Type = $typeof(#function);
|
||||
anyerr e;
|
||||
do
|
||||
{
|
||||
$Type! result = #function;
|
||||
if (catch err = result)
|
||||
{
|
||||
e = err;
|
||||
continue;
|
||||
}
|
||||
return result;
|
||||
} while (retries-- > 0);
|
||||
return e!;
|
||||
}
|
||||
|
||||
fn void main()
|
||||
{
|
||||
int! result = @retry(eventually_succeed());
|
||||
if (try result)
|
||||
{
|
||||
libc::printf("Got result: %d\n", result);
|
||||
}
|
||||
else
|
||||
{
|
||||
libc::printf("Failed :(\n");
|
||||
}
|
||||
}
|
||||
20
resources/examples/swap.c3
Normal file
20
resources/examples/swap.c3
Normal file
@@ -0,0 +1,20 @@
|
||||
module test;
|
||||
import libc;
|
||||
|
||||
/**
|
||||
* @checked a = b, b = a
|
||||
*/
|
||||
macro void @swap(&a, &b)
|
||||
{
|
||||
$typeof(a) temp = a;
|
||||
a = b;
|
||||
b = temp;
|
||||
}
|
||||
|
||||
fn void main()
|
||||
{
|
||||
int x = 123;
|
||||
int y = 456;
|
||||
@swap(x, y);
|
||||
libc::printf("x: %d y: %d\n", x, y);
|
||||
}
|
||||
@@ -4909,6 +4909,9 @@ void llvm_emit_call_expr(GenContext *c, BEValue *result_value, Expr *expr)
|
||||
{
|
||||
BEValue no_err;
|
||||
|
||||
// Emit the current stack into the thread local or things will get messed up.
|
||||
if (c->debug.last_ptr) llvm_store(c, c->debug.last_ptr, c->debug.stack_slot, type_alloca_alignment(type_voidptr));
|
||||
|
||||
// 17a. If we used the error var as the indirect recipient, then that will hold the error.
|
||||
// otherwise it's whatever value in be_value.
|
||||
BEValue error_holder = *result_value;
|
||||
@@ -4941,9 +4944,6 @@ void llvm_emit_call_expr(GenContext *c, BEValue *result_value, Expr *expr)
|
||||
// 17f. Emit the "after" block.
|
||||
llvm_emit_block(c, after_block);
|
||||
|
||||
// Emit the current stack into the thread local or things will get messed up.
|
||||
if (c->debug.last_ptr) llvm_store(c, c->debug.last_ptr, c->debug.stack_slot, type_alloca_alignment(type_voidptr));
|
||||
|
||||
// 17g. If void, be_value contents should be skipped.
|
||||
if (!prototype->ret_by_ref)
|
||||
{
|
||||
|
||||
@@ -2113,7 +2113,7 @@ static inline bool parse_doc_contract(ParseContext *c, AstId **docs_ref, DocDire
|
||||
switch (kind)
|
||||
{
|
||||
case DOC_DIRECTIVE_CHECKED:
|
||||
scratch_buffer_append("@require \"");
|
||||
scratch_buffer_append("@checked \"");
|
||||
break;
|
||||
case DOC_DIRECTIVE_ENSURE:
|
||||
scratch_buffer_append("@ensure \"");
|
||||
|
||||
@@ -1768,6 +1768,7 @@ bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *s
|
||||
};
|
||||
|
||||
if (!sema_expr_analyse_call_invocation(context, call_expr, callee, &failable)) return false;
|
||||
|
||||
Expr **args = call_expr->call_expr.arguments;
|
||||
VECEACH(params, i)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user