Skip to content

Commit

Permalink
feat: compiler in compiler
Browse files Browse the repository at this point in the history
  • Loading branch information
alexjercan committed May 22, 2024
1 parent 56e3def commit f4f0efc
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 0 deletions.
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ examples: all
./coolc examples/coin/server.cl examples/coin/message.cl --module net --module threading --module data --module random -o build/coin-server
./coolc examples/coin/client.cl examples/coin/message.cl --module net --module threading --module raylib -o build/coin-client

compiler: all
./coolc examples/compiler.cl --module prelude --module data -o build/compiler

dist: clean all
rm -rf coolc.tar.gz
tar -czf coolc.tar.gz coolc lib
Expand Down
138 changes: 138 additions & 0 deletions examples/compiler.cl
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
class Token {
value: Optional (* String *) <- new None;
pos: Int;

with_value(v: String): SELF_TYPE {
{ value <- new Some.init(v); self; }
};

with_position(p: Int): SELF_TYPE {
{ pos <- p; self; }
};

value(): Optional (* String *) { value };

to_string(): String { { abort(); ""; } };
};

class TokenEnd inherits Token {
to_string(): String { "END" };
};
class TokenIllegal inherits Token {
to_string(): String { "ILLEGAL" };
};
class TokenPlus inherits Token {
to_string(): String { "PLUS" };
};
class TokenInt inherits Token {
to_string(): String { "INT_LITERAL" };
};

class Tokenizer {
buffer: String;
pos: Int;
read_pos: Int;
ch: Byte;

bEOF: Byte <- new Byte.from_int(0);
bPLUS: Byte <- new Byte.from_string("+");

init(text: String): SELF_TYPE {
{
buffer <- text;
read_char();
self;
}
};

peek_char(): Byte {
if buffer.length() <= read_pos then
bEOF
else
buffer.at(read_pos)
fi
};

read_char(): Byte {
{
ch <- peek_char();

pos <- read_pos;
read_pos <- read_pos + 1;

ch;
}
};

skip_whitespaces(): Object {
while ch.isspace() loop read_char() pool
};

next_token(): Token {
{
skip_whitespaces();

let position: Int <- pos
in
if ch = bEOF then
{ read_char(); new TokenEnd; }
else if ch = bPLUS then
{ read_char(); new TokenPlus.with_position(position); }
else if ch.isdigit() then
{
while ch.isdigit() loop read_char() pool;
let v: String <- buffer.substr(position, pos - position)
in new TokenInt.with_position(position).with_value(v);
}
else
{ read_char(); new TokenIllegal.with_value(buffer.substr(position, 1)).with_position(position); }
fi fi fi;
}
};

tokenize(): List (* Token *) {
let token: Token <- next_token(),
result: List <- new List.single(token)
in
{
while case token of t: TokenEnd => false; t: Token => true; esac loop
{
token <- next_token();
result <- result.append(token);
}
pool;

result;
}
};
};

class Main {
main(): Object {
let text: String <- new IO.in_string(),
tokens: List (* Token *) <- new Tokenizer.init(text).tokenize(),
iter: List <- tokens
in
while not isvoid iter loop
{
case iter.value() of
t: Token =>
{
new IO.out_string(t.to_string());
case t.value() of
v: None => "";
v: Some => case v.value() of
v: String => new IO.out_string("(").out_string(v).out_string(")");
esac;
esac;

new IO.out_string("\n");
};
o: Object => abort();
esac;

iter <- iter.next();
}
pool
};
};
15 changes: 15 additions & 0 deletions lib/data/optional.cl
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class Optional {};

class None inherits Optional {};
class Some inherits Optional {
value: Object;

init(v: Object): SELF_TYPE {
{
value <- v;
self;
}
};

value(): Object { value };
};
14 changes: 14 additions & 0 deletions lib/prelude/prelude.cl
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ class String inherits Object {

length(): Int { l };

at(i: Int): Byte { new Byte.from_string(substr(i, 1)) };

split(delim: String): Tuple {
let s: String <- case self of me: String => me; esac,
i: Int <- 0,
Expand Down Expand Up @@ -210,6 +212,18 @@ class Byte {
from_int(x: Int): Byte extern;
to_int(): Int extern;

isspace(): Bool {
let c: String <- to_string()
in (c = " ").or(c = "\n")
};

isdigit(): Bool {
let zero: Int <- new Byte.from_string("0").to_int(),
nine: Int <- new Byte.from_string("9").to_int(),
c: Int <- to_int()
in (zero <= c).and(c <= nine)
};

equals(x: Object): Bool {
case x of me: Byte => me.to_int() = to_int(); esac
};
Expand Down

0 comments on commit f4f0efc

Please sign in to comment.