Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/cx
*.c
harpy
*.txt
13 changes: 13 additions & 0 deletions examples/dot_anon.cx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//# 67
struct Foo {
int x;
static Foo new() => .{30}
static int get(Foo f) => f.x
}

int get(Foo f) => f.x

int main() {
Foo f = .new();
return get(.{7}) + Foo.get(.new()) + f.x;
}
9 changes: 9 additions & 0 deletions examples/dot_anon2.cx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//! name: Fernando\n
import std.string;
import std.io;

int main() {
String name = .from("Fernando");
printf("name: %s\n", name.ptr);
return 0;
}
10 changes: 10 additions & 0 deletions examples/dot_anon3.cx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//# 0

enum Foo {
Bar,
}

int main() {
Foo f = .Bar;
return f;
}
26 changes: 26 additions & 0 deletions examples/foreach.cx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//# 0
import std.array;
import std.stack;
import std.io;

int main() {
Array<int> arr = .new(4);
defer arr.free();

arr.push(60);
arr.push(7);

int num = 0;
foreach k, n; arr {
printf("%d\n", k);
num += n;
}

foreach &n; arr {
printf("%p\n", (void*) n);
}

printf("Result: %d\n", num);

return 0;
}
2 changes: 1 addition & 1 deletion examples/generics4.cx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,6 @@ int main() {
Bar<int> bar = {&f};
(*bar.s).val = 67;
Cool<int>.e("Fernando", 18);
Entry<int>* entry = Entry<int>.create("Fernando", 37);
Entry<int>* entry = .create("Fernando", 37);
return foo.val;
}
26 changes: 26 additions & 0 deletions examples/map.cx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//# 0
import std.lib;
import std.io;

struct Fun<T, U> {
static U* map(T* data, u32 len, U(T) fn) {
U* result = malloc(sizeof(U) * len);
for (u32 i = 0; i < len; i++) result[i] = fn(data[i]);
return result;
}
}

float toFloat(int x) => (float) x * 1.5F

int main() {
int[5] nums = [1, 2, 3, 4, 5];

// float* floats = Fun<int, float>.map(nums, 5, fn float(int x) => (float) x * 1.5f);
float* floats = Fun<int, float>.map(nums, 5, toFloat);
defer free(floats);

for (u32 i = 0; i < 5; i++)
printf("%f\n", floats[i]);

return 0;
}
10 changes: 10 additions & 0 deletions examples/multi_var_decl.cx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//# 67
struct Foo {
float x, y;
}

int main() {
int x, y = 2, 7;
Foo f = {y = 10F, x = 20F};
return (x * (int)(f.x + f.y)) + y;
}
18 changes: 18 additions & 0 deletions examples/slice.cx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//! CX!\n.cx\n
import std.string;
import std.slice;
import std.io;

int main() {
char* filename = "test.cx";
size_t size = filename.length;

Slice<char> ext = filename[-3..size];
if ext === ".cx" {
printf("CX!\n");
}

printf("%.*s\n", ext.length, ext.ptr);

return 0;
}
5 changes: 2 additions & 3 deletions examples/std/array.cx → examples/stdlib/array.cx
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,15 @@ import std.array;
alias Value = int!ArrayError

int main() {
Array<int> arr = Array<int>.new(1);
Array<int> arr = .new(1);
defer arr.free();

arr.push(60);
arr.push(7);
Value e = arr.get(2);

if !e.valid {
if !e.valid
printf("Error: %d\n", e.error);
}

Value v1 = arr.get(0);
Value v2 = arr.get(1);
Expand Down
2 changes: 1 addition & 1 deletion examples/std/box.cx → examples/stdlib/box.cx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ import std.box;
import std.io;

int main() {
Box<int> val = Box<int>.of(67);
Box<int> val = .of(67);
return val.unwrap();
}
File renamed without changes.
6 changes: 3 additions & 3 deletions examples/std/hashmap.cx → examples/stdlib/hashmap.cx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import std.hashmap;
import std.io;

int main() {
HashMap<int> map = HashMap<int>.new(16);
defer map.delete();
HashMap<int> map = .new(16);
defer map.free();

map.set("age", 18);
map.set("year", 2026);
map.set("port", 8080);
map.set("port", 8080);

Box<int> age = map.get("age");
if !age.isEmpty()
Expand Down
File renamed without changes.
20 changes: 20 additions & 0 deletions examples/stdlib/slice.cx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//! view[0]: 20\nfoo: 3.000000\n
import std.slice;
import std.io;

Slice<float> foo() {
float[] f = [0f, 2f, 3f, 1f, 4f];
return f[2...3]; // heap
}

int main() {
int[5] arr = [10, 20, 30, 40, 50];
Slice<int> view = arr[1..2]; // Slice<int>.of(arr, 1, 2);
printf("view[0]: %d\n", view.get(0));

Slice<float> f = foo();
defer f.free();
printf("foo: %f\n", f.get(0));

return 0;
}
File renamed without changes.
4 changes: 2 additions & 2 deletions examples/std/str.cx → examples/stdlib/str.cx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import std.string;
import std.io;

int main() {
String s1 = String.from("Fernando");
String s2 = String.from(" the ");
String s1 = .from("Fernando");
String s2 = .from(" the ");

defer s1.free();
defer s2.free();
Expand Down
97 changes: 92 additions & 5 deletions src/backend/codegen.d
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,11 @@ final class CodeGen
private:
Program program;
TypeRegistry types;
TypeResolver resolver;

TypeExpr actualType;
TypeExpr fnType;

bool isFnStatic;
bool genHeaderFile;
string headerFile;
Expand Down Expand Up @@ -150,6 +153,10 @@ private:
RawStmt n = cast(RawStmt) node;
return emit(indent("/* raw block */", ind) ~ n.code, 0);

case NodeKind.VarDecl:
data ~= compileVarDecl(cast(VarDecl)node, 0);
return;

default:
emit("/* invalid decl */", ind);
return;
Expand Down Expand Up @@ -277,6 +284,46 @@ private:
emit("}", ind);
return "";

case NodeKind.ForEachStmt:
ForEachStmt fe = cast(ForEachStmt) node;

string sname = fe.value.type_expr.toStr();
string value = compileExpr(fe.value);

FnDecl iter = resolver.findMethod(sname, "iter");
string iterator = iter.type_expr.toString();

string temp = format("__it%d", tmp++);
string it = format("%s %s = %s_iter(&%s);", iterator, temp, sname, value);

bool isRef = fe.v.kind == NodeKind.UnaryExpr;
string val = isRef ? compileExpr((cast(UnaryExpr) fe.v).val) : compileExpr(fe.v);

// writeln(sname);
// writeln(value);
// writeln(iterator);
// writeln(temp);
// writeln(it);

emit(it, ind);
emit(format("for (;%s.offset < %s.length; %s.offset++)", temp, temp, temp), ind);
emit(format("{"), ind);
if (fe.k !is null)
emit(format("size_t %s = %s.offset;", compileExpr(fe.k), temp), ind);
emit(format("__typeof__(%s(%s.ptr)) %s = %s(%s.ptr[%s.offset]);",
isRef ? "" : "*", temp, val, isRef ? "&" : "", temp, temp), ind+4);
foreach (Node n; fe.body)
emit(compileStmt(n, ind), ind);
emit(format("}"), ind);

// Iterator<int> __it1 = arr.iter(); OK
// for (; __it1.offset < __it1.length; __it1.offset++) {
// int n = __it1.ptr[__it1.offset];
// num += n;
// }

return "";

default:
return indent("/* invalid stmt */", ind);
}
Expand Down Expand Up @@ -402,8 +449,18 @@ private:
BinaryExpr binary = cast(BinaryExpr) node;
string left = compileExpr(binary.left);
string right = compileExpr(binary.right);
if (isString(binary.left.type_expr) && isString(binary.right.type_expr) && binary.op == TokenKind.EEEquals)
return format("strcmp(%s, %s) == 0", left, right);
if (binary.op == TokenKind.EEEquals)
{
if (isString(binary.left.type_expr) && isString(binary.right.type_expr))
return format("strcmp(%s, %s) == 0", left, right);
if (isStruct(binary.left.type_expr))
{
string name = binary.left.type_expr.toStr();
FnDecl fn = resolver.findMethod(name, "cmp");
if (fn)
return format("%s_cmp(&%s, %s)", name, left, right);
}
}
return format("%s %s %s", left, getOp(binary.op), right);

case NodeKind.UnaryExpr:
Expand Down Expand Up @@ -516,8 +573,24 @@ private:
return format("(%s)%s", n.type_expr.toString(), compileExpr(n.expr));

case NodeKind.IndexExpr:
IndexExpr idx = cast(IndexExpr) node;
return format("%s[%s]", compileExpr(idx.value), compileExpr(idx.idx));
IndexExpr idxExpr = cast(IndexExpr) node;
string val = compileExpr(idxExpr.value);
// writeln(idxExpr.idx);
// writeln(idxExpr.value);
// writeln("val: ", val);
if (RangeExpr range = cast(RangeExpr) idxExpr.idx)
{
string left = compileExpr(range.left);
string right = compileExpr(range.right);

if (range.left.kind == NodeKind.UnaryExpr)
left = right ~ left;

return format("Slice_%s_%s(%s, %s, %s)",
idxExpr.value.type_expr.toStr(), range.isCopy ? "copyOf" : "of",
val, left, right);
}
return format("%s[%s]", val, compileExpr(idxExpr.idx));

case NodeKind.GroupExpr:
return "(" ~ compileExpr((cast(GroupExpr) node).val) ~ ")";
Expand Down Expand Up @@ -585,6 +658,14 @@ private:

string compileMemberExpr(MemberExpr node)
{
if (node.right.kind == NodeKind.StructLit)
{
// string expr = compileExpr(node.right);
// writeln(expr);
// return expr;
return compileExpr(node.right);
}

TypeExpr type = node.left.type_expr;
string typeName, id;
bool isArrow;
Expand Down Expand Up @@ -632,6 +713,11 @@ private:
id = format("tmp_%d", tmp++);
emit(format("%s %s = %s;", m.right.type_expr, id, member), 4);
}
}
else if (CallExpr c = cast(CallExpr) node.left)
{
id = format("tmp_%d", tmp++);
emit(format("%s %s = %s;", c.type_expr, id, compileExpr(c)), 4);
}
if (id != "")
{
Expand Down Expand Up @@ -871,14 +957,15 @@ private:

public:
this(Program program, TypeRegistry types, bool[string] staticFunctions, bool noHeader, bool genHeaderFile,
string headerFile, ImportResolverContext* context, bool isCpp)
string headerFile, ImportResolverContext* context, bool isCpp, TypeResolver resolver)
{
this.program = program;
this.types = types;
this.fnStatics = staticFunctions;
this.genHeaderFile = genHeaderFile;
this.headerFile = headerFile;
this.context = context;
this.resolver = resolver;
if (noHeader) return;
cxHeader ~= `
#ifndef __CLANG_STDINT_H
Expand Down
2 changes: 1 addition & 1 deletion src/env.d
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module env;

const string COMPILER_VERSION = "0.2.0";
const string COMPILER_VERSION = "0.2.1";
const string GITHUB_REPO = "https://github.com/FernandoTheDev/cx.git";
Loading
Loading