aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.exrc1
-rw-r--r--README58
-rw-r--r--src/codegen.c4
-rw-r--r--src/lexer.c13
-rw-r--r--src/lexer.h4
-rw-r--r--src/parser.c25
-rw-r--r--src/parser.h5
7 files changed, 102 insertions, 8 deletions
diff --git a/.exrc b/.exrc
index 432baf7..932e8ae 100644
--- a/.exrc
+++ b/.exrc
@@ -1 +1,2 @@
set makeprg=./make
+autocmd BufRead README setlocal et tw=73
diff --git a/README b/README
index fe2ab13..2ea9205 100644
--- a/README
+++ b/README
@@ -1 +1,57 @@
-Oryx — Programming Made Better
+ Oryx — Programming Made Better
+
+ ┌────────────────────────────┐
+ │ Existing Language Features │
+ └────────────────────────────┘
+
+1. The following datatypes are supported. The unsigned integer types
+ default to the systems word size (typically 64 bits).
+
+ i8, i16, i32, i64, i128, int
+ u8, u16, u32, u64, u128, uint
+
+2. C-style block comments. Line comments are intentionally not
+ included.
+
+3. Declaration of mutable variables with optional type-inference. The
+ syntax is simple and consistent regardless of if type-inference is
+ used or not. Variables are also zero-initialized unless ‘…’
+ (U+2026 HORIZONTAL ELLIPSIS) or ‘...’ is given as a value.
+
+ x: int; /* Declare a zero-initialized integer */
+ x: int = 69; /* Declare an integer and set it to 69 */
+ x: = 69; /* Same as above but infer the type */
+ x := 69; /* Recommended style when inferring types */
+ x: int = …; /* Declare an uninitialized integer (preferred) */
+ x: int = ...; /* Same as above when Unicode is not possible */
+
+4. Declaration of constant variables with optional type-inference
+ including constants of arbitrary precision. The syntax is
+ intentionally designed to be consistent with mutable variable
+ declaration.
+
+ Constants are unordered, meaning that a constant may refer to another
+ constant that is declared later in the source file.
+
+ FOO: u8 : BAR
+ BAR: u8 : 69;
+
+ REALLY_BIG :: 123'456'789'876'543'210;
+
+ pub MyFunc :: () int {
+ return BAR;
+ }
+
+5. Constants of arbitrary precision (overflow is not possible), with ‘'’
+ (U+0027 APOSTROPHE) as an optional digit seperator.
+
+ REALLY_BIG :: 123'456'789'876'543'210;
+
+6. No implicit type conversions between types. This includes between
+ different integer types which may have the same size (i.e. int and
+ int64)
+
+ pub MyFunc :: () {
+ x: int = 69;
+ y: i64 = x; /* Compile-time error */
+ }
diff --git a/src/codegen.c b/src/codegen.c
index 6fc7848..665f071 100644
--- a/src/codegen.c
+++ b/src/codegen.c
@@ -240,6 +240,10 @@ codegendecl(struct cgctx ctx, idx_t i)
assert(ctx.ast.kinds[i] == ASTDECL);
+ /* Don’t assign a default value to ‘x: int = …’ */
+ if (ctx.aux.buf[p.lhs].decl.isundef)
+ return fwdnode(ctx.ast, i);
+
if (!ctx.types[i].isfloat && ctx.aux.buf[p.lhs].decl.isstatic) {
strview_t sv = ctx.toks.strs[ctx.ast.lexemes[i]];
/* TODO: Namespace the name */
diff --git a/src/lexer.c b/src/lexer.c
index 30686d8..a613585 100644
--- a/src/lexer.c
+++ b/src/lexer.c
@@ -70,6 +70,10 @@ lexstring(const uchar *code, size_t codesz)
data.kinds[data.len++] = ch;
break;
+ case RUNE_C(0x2026): /* U+2026 HORIZONTAL ELLIPSIS */
+ data.kinds[data.len++] = LEXELIP;
+ break;
+
/* Single- or double-byte literals */
case '/':
if (code < end && code[0] == '*') {
@@ -80,7 +84,6 @@ lexstring(const uchar *code, size_t codesz)
data.kinds[data.len++] = ch;
break;
-
case '<': case '>':
data.kinds[data.len++] = ch;
@@ -91,6 +94,13 @@ lexstring(const uchar *code, size_t codesz)
}
break;
+ case '.':
+ if (unlikely(end - code < 2) || code[0] != '.' || code[1] != '.')
+ goto fallback;
+ code += 2;
+ data.kinds[data.len++] = LEXELIP;
+ break;
+
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
data.kinds[data.len] = LEXNUM;
@@ -112,6 +122,7 @@ lexstring(const uchar *code, size_t codesz)
break;
default:
+fallback:
if (!rune_is_xids(ch))
continue;
diff --git a/src/lexer.h b/src/lexer.h
index 5436030..fb63fd8 100644
--- a/src/lexer.h
+++ b/src/lexer.h
@@ -13,6 +13,10 @@ enum {
LEXEOF, /* End of token stream */
LEXIDENT, /* Identifier */
LEXNUM, /* Numeric constant */
+ LEXELIP, /* Ellipsis */
+
+ /* NOTE: Make sure that the enumerations above this comment don’t
+ conflict with the following explicitly assigned enumerations! */
LEXAMP = '&',
LEXCOLON = ':',
diff --git a/src/parser.c b/src/parser.c
index 5b12e21..46a1fb6 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -128,6 +128,7 @@ parsedecl(ast_t *ast, aux_t *aux, lexemes_t toks, bool toplvl)
}
aux->buf[j].decl.isstatic = toplvl;
+ aux->buf[j].decl.isundef = false;
if (toplvl && toks.kinds[toksidx] == LEXIDENT
&& strview_eq(SV("pub"), toks.strs[toksidx]))
{
@@ -165,11 +166,27 @@ parsedecl(ast_t *ast, aux_t *aux, lexemes_t toks, bool toplvl)
err("parser: Expected colon, equals, or semicolon");
}
- bool func = toks.kinds[toksidx] == LEXLPAR;
- if (func && ast->kinds[i] == ASTDECL)
- err("Cannot assign function to mutable variable");
+ idx_t rhs;
+ bool func = false;
+
+ switch (toks.kinds[toksidx]) {
+ case LEXLPAR:
+ func = true;
+ if (ast->kinds[i] == ASTDECL)
+ err("Cannot assign function to mutable variable");
+ rhs = parsefunc(ast, aux, toks);
+ break;
+ case LEXELIP:
+ toksidx++;
+ if (ast->kinds[i] == ASTCDECL)
+ err("parser: Cannot assign to ‘…’ in constant declaration");
+ rhs = AST_EMPTY;
+ aux->buf[j].decl.isundef = true;
+ break;
+ default:
+ rhs = parseexpr(ast, aux, toks);
+ }
- idx_t rhs = (func ? parsefunc : parseexpr)(ast, aux, toks);
ast->kids[i].rhs = rhs;
if (!func && toks.kinds[toksidx++] != LEXSEMI)
err("parser: Expected semicolon");
diff --git a/src/parser.h b/src/parser.h
index 9f7bf5e..d8991c0 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -71,8 +71,9 @@ typedef struct {
union {
struct {
idx_t type;
- bool ispub;
- bool isstatic;
+ bool ispub : 1;
+ bool isstatic : 1;
+ bool isundef : 1;
} decl;
} *buf;
size_t len, cap;