Fix stack setting after error return. Some fixes to examples.

This commit is contained in:
Christoffer Lerno
2022-07-02 10:08:45 +02:00
committed by Christoffer Lerno
parent b1d83e2ccd
commit bb28f6e61c
12 changed files with 140 additions and 110 deletions

View File

@@ -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;
}

View 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;
}

View File

@@ -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)];

View File

@@ -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;
}

View File

@@ -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();
}

View File

@@ -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());
}

View File

@@ -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;
}

View 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");
}
}

View 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);
}

View File

@@ -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)
{

View File

@@ -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 \"");

View File

@@ -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)
{