Add typing syntax

This commit is contained in:
George Marques 2018-05-29 23:16:51 -03:00
parent cfcb6e11f2
commit 8aab9a06d4
No known key found for this signature in database
GPG key ID: 046BD46A3201E43D
6 changed files with 147 additions and 76 deletions

View file

@ -1735,7 +1735,9 @@ void GDScriptLanguage::get_reserved_words(List<String> *p_words) const {
"NAN",
"self",
"true",
"void",
// functions
"as",
"assert",
"breakpoint",
"class",

View file

@ -430,6 +430,10 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser::
return dst_addr;
} break;
case GDScriptParser::Node::TYPE_CAST: {
const GDScriptParser::CastNode *cn = static_cast<const GDScriptParser::CastNode *>(p_expression);
return _parse_expression(codegen, cn->source_node, p_stack_level);
} break;
case GDScriptParser::Node::TYPE_OPERATOR: {
//hell breaks loose

View file

@ -1087,6 +1087,27 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s
break;
}
/*****************/
/* Parse Casting */
/*****************/
bool has_casting = expr->type == Node::TYPE_CAST;
if (tokenizer->get_token() == GDScriptTokenizer::TK_PR_AS) {
if (has_casting) {
_set_error("Unexpected 'as'.");
return NULL;
}
CastNode *cn = alloc_node<CastNode>();
DataType casttype;
if (!_parse_type(casttype)) {
_set_error("Expected type after 'as'.");
return NULL;
}
has_casting = true;
cn->source_node = expr;
expr = cn;
}
/******************/
/* Parse Operator */
/******************/
@ -1110,7 +1131,7 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s
//assign, if allowed is only allowed on the first operator
#define _VALIDATE_ASSIGN \
if (!p_allow_assign) { \
if (!p_allow_assign || has_casting) { \
_set_error("Unexpected assign."); \
return NULL; \
} \
@ -2488,6 +2509,14 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
Node *assigned = NULL;
if (tokenizer->get_token() == GDScriptTokenizer::TK_COLON) {
DataType vartype;
if (!_parse_type(vartype)) {
_set_error("Expected type for variable.");
return;
}
}
if (tokenizer->get_token() == GDScriptTokenizer::TK_OP_ASSIGN) {
tokenizer->advance();
@ -3150,7 +3179,6 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
//class inside class :D
StringName name;
StringName extends;
if (tokenizer->get_token(1) != GDScriptTokenizer::TK_IDENTIFIER) {
@ -3279,6 +3307,14 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
tokenizer->advance();
if (tokenizer->get_token() == GDScriptTokenizer::TK_COLON) {
DataType argtype;
if (!_parse_type(argtype)) {
_set_error("Expected type for argument.");
return;
}
}
if (defaulting && tokenizer->get_token() != GDScriptTokenizer::TK_OP_ASSIGN) {
_set_error("Default parameter expected.");
@ -3386,6 +3422,14 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
}
}
if (tokenizer->get_token() == GDScriptTokenizer::TK_FORWARD_ARROW) {
DataType rettype;
if (!_parse_type(rettype, true)) {
_set_error("Expected return type for function.");
return;
}
}
if (!_enter_indent_block(block)) {
_set_error("Indented block expected.");
@ -4113,6 +4157,14 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED;
if (tokenizer->get_token() == GDScriptTokenizer::TK_COLON) {
DataType vartype;
if (!_parse_type(vartype)) {
_set_error("Expected type for class variable.");
return;
}
}
if (tokenizer->get_token() == GDScriptTokenizer::TK_OP_ASSIGN) {
#ifdef DEBUG_ENABLED
@ -4272,6 +4324,14 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
constant.identifier = tokenizer->get_token_literal();
tokenizer->advance();
if (tokenizer->get_token() == GDScriptTokenizer::TK_COLON) {
DataType consttype;
if (!_parse_type(consttype)) {
_set_error("Expected type for class constant.");
return;
}
}
if (tokenizer->get_token() != GDScriptTokenizer::TK_OP_ASSIGN) {
_set_error("Constant expects assignment.");
return;
@ -4423,6 +4483,31 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
}
}
bool GDScriptParser::_parse_type(DataType &r_type, bool p_can_be_void) {
tokenizer->advance();
r_type.has_type = true;
switch (tokenizer->get_token()) {
case GDScriptTokenizer::TK_IDENTIFIER: {
StringName id = tokenizer->get_token_identifier();
} break;
case GDScriptTokenizer::TK_BUILT_IN_TYPE: {
} break;
case GDScriptTokenizer::TK_PR_VOID: {
if (!p_can_be_void) {
return false;
}
} break;
default: {
return false;
}
}
tokenizer->advance();
return true;
}
void GDScriptParser::_set_error(const String &p_error, int p_line, int p_column) {
if (error_set)

View file

@ -39,6 +39,39 @@
class GDScriptParser {
public:
struct ClassNode;
struct DataType {
enum {
BUILTIN,
NATIVE,
SCRIPT,
GDSCRIPT,
CLASS
} kind;
bool has_type;
Variant::Type builtin_type;
StringName native_type;
Ref<Script> script_type;
ClassNode *class_type;
DataType *meta_type;
DataType() :
has_type(false),
meta_type(NULL),
builtin_type(Variant::NIL),
class_type(NULL) {}
~DataType() {
if (meta_type) {
memdelete(meta_type);
}
}
};
struct Node {
enum Type {
@ -55,6 +88,7 @@ public:
TYPE_OPERATOR,
TYPE_CONTROL_FLOW,
TYPE_LOCAL_VAR,
TYPE_CAST,
TYPE_ASSERT,
TYPE_BREAKPOINT,
TYPE_NEWLINE,
@ -65,6 +99,9 @@ public:
int column;
Type type;
virtual DataType get_datatype() const { return DataType(); }
virtual void set_datatype(DataType p_datatype) {}
virtual ~Node() {}
};
@ -340,6 +377,11 @@ public:
}
};
struct CastNode : public Node {
Node *source_node;
CastNode() { type = TYPE_CAST; }
};
struct AssertNode : public Node {
Node *condition;
AssertNode() { type = TYPE_ASSERT; }
@ -362,76 +404,6 @@ public:
};
};
/*
struct OperatorNode : public Node {
DataType return_cache;
Operator op;
Vector<Node*> arguments;
virtual DataType get_datatype() const { return return_cache; }
OperatorNode() { type=TYPE_OPERATOR; return_cache=TYPE_VOID; }
};
struct VariableNode : public Node {
DataType datatype_cache;
StringName name;
virtual DataType get_datatype() const { return datatype_cache; }
VariableNode() { type=TYPE_VARIABLE; datatype_cache=TYPE_VOID; }
};
struct ConstantNode : public Node {
DataType datatype;
Variant value;
virtual DataType get_datatype() const { return datatype; }
ConstantNode() { type=TYPE_CONSTANT; }
};
struct BlockNode : public Node {
Map<StringName,DataType> variables;
List<Node*> statements;
BlockNode() { type=TYPE_BLOCK; }
};
struct ControlFlowNode : public Node {
FlowOperation flow_op;
Vector<Node*> statements;
ControlFlowNode() { type=TYPE_CONTROL_FLOW; flow_op=FLOW_OP_IF;}
};
struct MemberNode : public Node {
DataType datatype;
StringName name;
Node* owner;
virtual DataType get_datatype() const { return datatype; }
MemberNode() { type=TYPE_MEMBER; }
};
struct ProgramNode : public Node {
struct Function {
StringName name;
FunctionNode*function;
};
Map<StringName,DataType> builtin_variables;
Map<StringName,DataType> preexisting_variables;
Vector<Function> functions;
BlockNode *body;
ProgramNode() { type=TYPE_PROGRAM; }
};
*/
enum CompletionType {
COMPLETION_NONE,
COMPLETION_BUILT_IN_TYPE_CONSTANT,
@ -515,6 +487,8 @@ private:
void _parse_class(ClassNode *p_class);
bool _end_statement();
bool _parse_type(DataType &r_type, bool p_can_be_void = false);
Error _parse(const String &p_base_path);
public:

View file

@ -101,6 +101,8 @@ const char *GDScriptTokenizer::token_names[TK_MAX] = {
"setget",
"const",
"var",
"as",
"void",
"enum",
"preload",
"assert",
@ -125,6 +127,7 @@ const char *GDScriptTokenizer::token_names[TK_MAX] = {
"'.'",
"'?'",
"':'",
"'->'",
"'$'",
"'\\n'",
"PI",
@ -197,6 +200,8 @@ static const _kws _keyword_list[] = {
{ GDScriptTokenizer::TK_PR_EXPORT, "export" },
{ GDScriptTokenizer::TK_PR_SETGET, "setget" },
{ GDScriptTokenizer::TK_PR_VAR, "var" },
{ GDScriptTokenizer::TK_PR_AS, "as" },
{ GDScriptTokenizer::TK_PR_VOID, "void" },
{ GDScriptTokenizer::TK_PR_PRELOAD, "preload" },
{ GDScriptTokenizer::TK_PR_ASSERT, "assert" },
{ GDScriptTokenizer::TK_PR_YIELD, "yield" },
@ -707,11 +712,9 @@ void GDScriptTokenizerText::_advance() {
if (GETCHAR(1) == '=') {
_make_token(TK_OP_ASSIGN_SUB);
INCPOS(1);
/*
} else if (GETCHAR(1)=='-') {
_make_token(TK_OP_MINUS_MINUS);
} else if (GETCHAR(1) == '>') {
_make_token(TK_FORWARD_ARROW);
INCPOS(1);
*/
} else {
_make_token(TK_OP_SUB);
}

View file

@ -106,6 +106,8 @@ public:
TK_PR_SETGET,
TK_PR_CONST,
TK_PR_VAR,
TK_PR_AS,
TK_PR_VOID,
TK_PR_ENUM,
TK_PR_PRELOAD,
TK_PR_ASSERT,
@ -131,6 +133,7 @@ public:
TK_QUESTION_MARK,
TK_COLON,
TK_DOLLAR,
TK_FORWARD_ARROW,
TK_NEWLINE,
TK_CONST_PI,
TK_CONST_TAU,