Skip to content

Commit

Permalink
Type aliases
Browse files Browse the repository at this point in the history
  • Loading branch information
Enalye committed Apr 15, 2020
1 parent 02588a0 commit 1563382
Show file tree
Hide file tree
Showing 5 changed files with 155 additions and 45 deletions.
25 changes: 25 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ You can easily define custom functions and types from D.
- Enumerations
- Classes
- Channels
- Type aliases

- Errors:
- Error Handling
Expand Down Expand Up @@ -824,6 +825,30 @@ Here, foo will be blocked until something is written on the channel, then it'll
* * *
# Type Aliases
A type alias allow types to be named differently, making long signatures shorter.
```cpp
func square(int i) int {
return i * i;
};
type MyFunc = func(int) int;
main {
MyFunc myFunc = &(MyFunc) square;
10:myFunc:printl;
}
```

You can also declare aliases in D by calling `addTypeAlias` on your `GrData`:
```d
data.addTypeAlias("MyInt", grInt);
```

* * *

# Error Handling

Error handling in Grimoire is done by raising/catching errors
Expand Down
100 changes: 65 additions & 35 deletions source/grimoire/compiler/data.d
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ class GrData {
/// They're pointer only defined by a name. \
/// Can only be used with primitives.
dstring[] _foreigns;
/// Type aliases
GrTypeAliasDefinition[] _typeAliases;
/// Enum types.
GrEnumDefinition[] _enumTypes;
/// Object types.
Expand All @@ -40,31 +42,6 @@ class GrData {
return grVoid;
}

/// Define an opaque pointer type.
GrType addForeign(dstring name) {
bool isDeclared;
foreach(foreign; _foreigns) {
if(foreign == name)
isDeclared = true;
}

if(!isDeclared)
_foreigns ~= name;

GrType type = GrBaseType.foreign;
type.mangledType = name;
return type;
}

/// Is the user-type defined ?
bool isForeign(dstring name) {
foreach(foreign; _foreigns) {
if(foreign == name)
return true;
}
return false;
}

/// Define an enum type.
GrType addEnum(dstring name, dstring[] fields) {
GrEnumDefinition enumDef = new GrEnumDefinition;
Expand Down Expand Up @@ -93,6 +70,31 @@ class GrData {
return stType;
}

/// Define an opaque pointer type.
GrType addForeign(dstring name) {
bool isDeclared;
foreach(foreign; _foreigns) {
if(foreign == name)
isDeclared = true;
}

if(!isDeclared)
_foreigns ~= name;

GrType type = GrBaseType.foreign;
type.mangledType = name;
return type;
}

/// Define an alias of another type.
GrType addTypeAlias(dstring name, GrType type) {
GrTypeAliasDefinition typeAlias = new GrTypeAliasDefinition;
typeAlias.name = name;
typeAlias.type = type;
_typeAliases ~= typeAlias;
return type;
}

/// Is the enum defined ?
bool isEnum(dstring name) {
foreach(enumType; _enumTypes) {
Expand All @@ -102,6 +104,33 @@ class GrData {
return false;
}

/// Is the class defined ?
bool isClass(dstring name) {
foreach(class_; _classTypes) {
if(class_.name == name)
return true;
}
return false;
}

/// Is the user-type defined ?
bool isForeign(dstring name) {
foreach(foreign; _foreigns) {
if(foreign == name)
return true;
}
return false;
}

/// Is the type alias defined ?
bool isTypeAlias(dstring name) {
foreach(typeAlias; _typeAliases) {
if(typeAlias.name == name)
return true;
}
return false;
}

/// Return the enum definition.
GrEnumDefinition getEnum(dstring name) {
import std.conv: to;
Expand All @@ -112,23 +141,24 @@ class GrData {
assert(false, "Undefined enum \'" ~ to!string(name) ~ "\'");
}

/// Is the struct defined ?
bool isClass(dstring name) {
/// Return the class definition.
GrClassDefinition getClass(dstring name) {
import std.conv: to;
foreach(class_; _classTypes) {
if(class_.name == name)
return true;
return class_;
}
return false;
assert(false, "Undefined class \'" ~ to!string(name) ~ "\'");
}

/// Return the struct definition.
GrClassDefinition getClass(dstring name) {
/// Return the type alias definition.
GrTypeAliasDefinition getTypeAlias(dstring name) {
import std.conv: to;
foreach(class_; _classTypes) {
if(class_.name == name)
return class_;
foreach(typeAlias; _typeAliases) {
if(typeAlias.name == name)
return typeAlias;
}
assert(false, "Undefined class_ \'" ~ to!string(name) ~ "\'");
assert(false, "Undefined \'" ~ to!string(name) ~ "\'");
}

/**
Expand Down
7 changes: 5 additions & 2 deletions source/grimoire/compiler/lexer.d
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ enum GrLexemeType {
and, or, xor, not,
increment, decrement,
identifier, integer, float_, boolean, string_,
main_, event_, class_, enum_, new_, copy, send, receive,
main_, type_, event_, class_, enum_, new_, copy, send, receive,
voidType, intType, floatType, boolType, stringType, arrayType, functionType, taskType, chanType, autoType,
if_, unless, else_, switch_, select, case_, while_, do_, until, for_, loop, return_, self,
kill, killAll, yield, break_, continue_,
Expand Down Expand Up @@ -626,6 +626,9 @@ package final class GrLexer {
case "main":
lex.type = GrLexemeType.main_;
break;
case "type":
lex.type = GrLexemeType.type_;
break;
case "event":
lex.type = GrLexemeType.event_;
break;
Expand Down Expand Up @@ -910,7 +913,7 @@ dstring grGetPrettyLexemeType(GrLexemeType operator) {
"and", "or", "xor", "not",
"++", "--",
"identifier", "const_int", "const_float", "const_bool", "const_str",
"main", "event", "class", "enum", "new", "copy", "send", "receive",
"main", "type", "event", "class", "enum", "new", "copy", "send", "receive",
"void", "int", "float", "bool", "string", "array", "var", "func", "task", "chan", "let",
"if", "unless", "else", "switch", "select", "case", "while", "do", "until", "for", "loop", "return", "self",
"kill", "killall", "yield", "break", "continue"
Expand Down
40 changes: 36 additions & 4 deletions source/grimoire/compiler/parser.d
Original file line number Diff line number Diff line change
Expand Up @@ -1513,6 +1513,7 @@ final class GrParser {
case voidType: .. case arrayType:
case autoType:
case identifier:
case type_:
skipExpression();
break;
default:
Expand Down Expand Up @@ -1544,6 +1545,9 @@ final class GrParser {
break;
case enum_:
parseEnumDeclaration();
break;
case type_:
parseTypeAliasDeclaration();
break;
case main_:
case event_:
Expand Down Expand Up @@ -1592,6 +1596,7 @@ final class GrParser {
case voidType: .. case arrayType:
case autoType:
case identifier:
case type_:
skipExpression();
break;
default:
Expand Down Expand Up @@ -1635,13 +1640,35 @@ final class GrParser {
break;
}
goto default;
case type_:
skipExpression();
break;
default:
logError("Invalid type", "The type should be either main, func, task or struct");
}
}
endGlobalScope();
}

/**
Declare a new alias of a type.
*/
private void parseTypeAliasDeclaration() {
checkAdvance();
if(get().type != GrLexemeType.identifier)
logError("Missing Identifier", "A type alias must be named");
const dstring typeAliasName = get().svalue;
checkAdvance();
if(get().type != GrLexemeType.assign)
logError("Missing =", "This should be an assignment");
checkAdvance();
GrType type = parseType(true);
if(get().type != GrLexemeType.semicolon)
logError("Missing ;", "The definition must end with a semicolon");

_data.addTypeAlias(typeAliasName, type);
}

private void parseEnumDeclaration() {
checkAdvance();
if(get().type != GrLexemeType.identifier)
Expand Down Expand Up @@ -1762,7 +1789,12 @@ final class GrParser {

GrLexeme lex = get();
if(!lex.isType) {
if(lex.type == GrLexemeType.identifier && _data.isClass(lex.svalue)) {
if(lex.type == GrLexemeType.identifier && _data.isTypeAlias(lex.svalue)) {
currentType = _data.getTypeAlias(lex.svalue).type;
checkAdvance();
return currentType;
}
else if(lex.type == GrLexemeType.identifier && _data.isClass(lex.svalue)) {
currentType.baseType = GrBaseType.class_;
currentType.mangledType = lex.svalue;
checkAdvance();
Expand Down Expand Up @@ -2340,7 +2372,7 @@ final class GrParser {
goto default;
break;
case identifier:
if(_data.isEnum(get().svalue) || _data.isClass(get().svalue) || _data.isForeign(get().svalue))
if(_data.isTypeAlias(get().svalue) || _data.isEnum(get().svalue) || _data.isClass(get().svalue) || _data.isForeign(get().svalue))
parseLocalDeclaration();
else
goto default;
Expand Down Expand Up @@ -3217,7 +3249,7 @@ final class GrParser {
type = parseType();
break;
case identifier:
if(_data.isEnum(get().svalue) || _data.isClass(get().svalue) || _data.isForeign(get().svalue))
if(_data.isTypeAlias(get().svalue) || _data.isEnum(get().svalue) || _data.isClass(get().svalue) || _data.isForeign(get().svalue))
type = parseType();
else
isTyped = false;
Expand Down Expand Up @@ -5063,7 +5095,7 @@ final class GrParser {
else {
if(hasParenthesis && get().type == GrLexemeType.rightParenthesis)
advance();
if(anonSignature.length)
if(signature.length != anonSignature.length)
logError("Invalid anonymous call", "The number of parameters does not match");
}

Expand Down
28 changes: 24 additions & 4 deletions source/grimoire/compiler/type.d
Original file line number Diff line number Diff line change
Expand Up @@ -137,11 +137,31 @@ GrType grGetForeignType(dstring name) {
return type;
}

/**
Define the content of a type alias. \
Not to be confused with GrType used by the type system.
---
type MyNewType = AnotherType;
---
*/
final class GrTypeAliasDefinition {
/// Identifier.
dstring name;
/// The type aliased.
GrType type;
}

/**
Define the content of an enum. \
Not to be confused with GrType used by the type system.
---
enum MyEnum {
field1;
field2;
}
---
*/
class GrEnumDefinition {
final class GrEnumDefinition {
/// Identifier.
dstring name;
/// List of field names.
Expand Down Expand Up @@ -172,15 +192,15 @@ class GrEnumDefinition {
}

/**
Define the content of an object. \
Define the content of a class. \
Not to be confused with GrType used by the type system.
---
object MyObject {
class MyClass {
// Fields
}
---
*/
class GrClassDefinition {
final class GrClassDefinition {
/// Identifier.
dstring name;
/// List of field types.
Expand Down

0 comments on commit 1563382

Please sign in to comment.