diff --git a/source/app.d b/source/app.d index 916f263..5034514 100644 --- a/source/app.d +++ b/source/app.d @@ -144,7 +144,7 @@ int main(string[] args) { break; } case "--version": { - writeln("Callisto compiler beta 0.2"); + writeln("Callisto compiler beta 0.3"); return 0; } case "-a": { diff --git a/source/backends/linux86.d b/source/backends/linux86.d index e6d7ca0..8b7e79c 100644 --- a/source/backends/linux86.d +++ b/source/backends/linux86.d @@ -534,4 +534,23 @@ class BackendLinux86 : CompilerBackend { NewConst(node.name, node.value); } + + override void CompileEnum(EnumNode node) { + if (node.enumType !in types) { + Error(node.error, "Enum base type '%s' doesn't exist", node.enumType); + } + if (node.name in types) { + Error(node.error, "Enum name is already used by type '%s'", node.enumType); + } + + types[node.name] = types[node.enumType]; + + foreach (i, ref name ; node.names) { + NewConst(format("%s.%s", node.name, name), node.values[i]); + } + + NewConst(format("%s.min", node.name), node.values.minElement()); + NewConst(format("%s.max", node.name), node.values.maxElement()); + NewConst(format("%s.sizeof", node.name), types[node.name].size); + } } diff --git a/source/backends/rm86.d b/source/backends/rm86.d index 5d81f4a..d8a4f72 100644 --- a/source/backends/rm86.d +++ b/source/backends/rm86.d @@ -495,4 +495,23 @@ class BackendRM86 : CompilerBackend { NewConst(node.name, node.value); } + + override void CompileEnum(EnumNode node) { + if (node.enumType !in types) { + Error(node.error, "Enum base type '%s' doesn't exist", node.enumType); + } + if (node.name in types) { + Error(node.error, "Enum name is already used by type '%s'", node.enumType); + } + + types[node.name] = types[node.enumType]; + + foreach (i, ref name ; node.names) { + NewConst(format("%s.%s", node.name, name), node.values[i]); + } + + NewConst(format("%s.min", node.name), node.values.minElement()); + NewConst(format("%s.max", node.name), node.values.maxElement()); + NewConst(format("%s.sizeof", node.name), types[node.name].size); + } } diff --git a/source/backends/y16.d b/source/backends/y16.d index 7d0c412..460ea1c 100644 --- a/source/backends/y16.d +++ b/source/backends/y16.d @@ -332,4 +332,23 @@ class BackendY16 : CompilerBackend { NewConst(node.name, node.value); } + + override void CompileEnum(EnumNode node) { + if (node.enumType !in types) { + Error(node.error, "Enum base type '%s' doesn't exist", node.enumType); + } + if (node.name in types) { + Error(node.error, "Enum name is already used by type '%s'", node.enumType); + } + + types[node.name] = types[node.enumType]; + + foreach (i, ref name ; node.names) { + NewConst(format("%s.%s", node.name, name), node.values[i]); + } + + NewConst(format("%s.min", node.name), node.values.minElement()); + NewConst(format("%s.max", node.name), node.values.maxElement()); + NewConst(format("%s.sizeof", node.name), types[node.name].size); + } } diff --git a/source/compiler.d b/source/compiler.d index bc503b5..302490f 100644 --- a/source/compiler.d +++ b/source/compiler.d @@ -36,6 +36,7 @@ class CompilerBackend { abstract void CompileStruct(StructNode node); abstract void CompileReturn(WordNode node); abstract void CompileConst(ConstNode node); + abstract void CompileEnum(EnumNode node); final void Error(Char, A...)(ErrorInfo error, in Char[] fmt, A args) { ErrorBegin(error); @@ -82,14 +83,8 @@ class Compiler { } break; } - case NodeType.Integer: { - backend.CompileInteger(cast(IntegerNode) inode); - break; - } - case NodeType.FuncDef: { - backend.CompileFuncDef(cast(FuncDefNode) inode); - break; - } + case NodeType.Integer: backend.CompileInteger(cast(IntegerNode) inode); break; + case NodeType.FuncDef: backend.CompileFuncDef(cast(FuncDefNode) inode); break; case NodeType.Include: { auto node = cast(IncludeNode) inode; auto path = format("%s/%s", dirName(node.error.file), node.path); @@ -129,10 +124,7 @@ class Compiler { backend.output ~= node.code; break; } - case NodeType.If: { - backend.CompileIf(cast(IfNode) inode); - break; - } + case NodeType.If: backend.CompileIf(cast(IfNode) inode); break; case NodeType.While: { auto node = cast(WhileNode) inode; @@ -152,10 +144,7 @@ class Compiler { backend.CompileWhile(node); break; } - case NodeType.Let: { - backend.CompileLet(cast(LetNode) inode); - break; - } + case NodeType.Let: backend.CompileLet(cast(LetNode) inode); break; case NodeType.Implements: { auto node = cast(ImplementsNode) inode; @@ -178,22 +167,11 @@ class Compiler { } break; } - case NodeType.Array: { - backend.CompileArray(cast(ArrayNode) inode); - break; - } - case NodeType.String: { - backend.CompileString(cast(StringNode) inode); - break; - } - case NodeType.Struct: { - backend.CompileStruct(cast(StructNode) inode); - break; - } - case NodeType.Const: { - backend.CompileConst(cast(ConstNode) inode); - break; - } + case NodeType.Array: backend.CompileArray(cast(ArrayNode) inode); break; + case NodeType.String: backend.CompileString(cast(StringNode) inode); break; + case NodeType.Struct: backend.CompileStruct(cast(StructNode) inode); break; + case NodeType.Const: backend.CompileConst(cast(ConstNode) inode); break; + case NodeType.Enum: backend.CompileEnum(cast(EnumNode) inode); break; default: assert(0); } } @@ -216,7 +194,8 @@ class Compiler { case NodeType.Feature: case NodeType.Requires: case NodeType.Struct: - case NodeType.Const: { + case NodeType.Const: + case NodeType.Enum: { header ~= node; break; } diff --git a/source/parser.d b/source/parser.d index b2eabca..96df100 100644 --- a/source/parser.d +++ b/source/parser.d @@ -1,6 +1,7 @@ module callisto.parser; import std.conv; +import std.range; import std.stdio; import std.format; import std.algorithm; @@ -24,7 +25,8 @@ enum NodeType { Array, String, Struct, - Const + Const, + Enum } class Node { @@ -278,6 +280,28 @@ class ConstNode : Node { } } +class EnumNode : Node { + string name; + string enumType; + string[] names; + long[] values; + + this(ErrorInfo perror) { + type = NodeType.Enum; + error = perror; + } + + override string toString() { + string ret = format("enum %s : %s\n", name, enumType); + + foreach (i, ref name ; names) { + ret ~= format(" %s = %d\n", name, values[i]); + } + + return ret ~ "end\n"; + } +} + class ParserError : Exception { this() { super("", "", 0); @@ -682,6 +706,50 @@ class Parser { return ret; } + Node ParseEnum() { + auto ret = new EnumNode(GetError()); + parsing = NodeType.Enum; + + Next(); + Expect(TokenType.Identifier); + ret.name = tokens[i].contents; + ret.enumType = "cell"; + + Next(); + Expect(TokenType.Identifier); + + if (tokens[i].contents == ":") { + Next(); + Expect(TokenType.Identifier); + ret.enumType = tokens[i].contents; + + Next(); + Expect(TokenType.Identifier); + } + + while (true) { + if (tokens[i].contents == "end") break; + + ret.names ~= tokens[i].contents; + Next(); + Expect(TokenType.Identifier); + + if (tokens[i].contents == "=") { + Next(); + Expect(TokenType.Integer); + + ret.values ~= parse!long(tokens[i].contents); + Next(); + Expect(TokenType.Identifier); + } + else { + ret.values ~= ret.values.empty()? 0 : ret.values[$ - 1] + 1; + } + } + + return ret; + } + Node ParseStatement() { switch (tokens[i].type) { case TokenType.Integer: { @@ -702,6 +770,7 @@ class Parser { case "struct": return ParseStruct(); case "version": return ParseVersion(); case "const": return ParseConst(); + case "enum": return ParseEnum(); default: return new WordNode(GetError(), tokens[i].contents); } }