From 665d7526867f52b12d62d861643c0042e797e165 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 19 Oct 2016 00:35:34 +0200 Subject: [PATCH] - added 'null' token to the ZScript parser which is needed for null pointers. - removed function declaration parser from DECORATE because it is not needed anymore. - fixed: comparison operators could not handle names. --- src/sc_man_scanner.re | 1 + src/sc_man_tokens.h | 1 + src/scripting/codegeneration/codegen.cpp | 20 +- src/scripting/decorate/thingdef_parse.cpp | 264 ---------------------- src/scripting/zscript/zcc-parse.lemon | 7 + src/scripting/zscript/zcc_exprlist.h | 1 + src/scripting/zscript/zcc_parser.cpp | 1 + 7 files changed, 23 insertions(+), 272 deletions(-) diff --git a/src/sc_man_scanner.re b/src/sc_man_scanner.re index ba0e9a8e5..caeb18f8c 100644 --- a/src/sc_man_scanner.re +++ b/src/sc_man_scanner.re @@ -171,6 +171,7 @@ std2: 'global' { RET(TK_Global); } 'self' { RET(TK_Self); } 'stop' { RET(TK_Stop); } + 'null' { RET(TK_Null); } 'is' { RET(TK_Is); } 'replaces' { RET(TK_Replaces); } diff --git a/src/sc_man_tokens.h b/src/sc_man_tokens.h index 934558d54..69927883c 100644 --- a/src/sc_man_tokens.h +++ b/src/sc_man_tokens.h @@ -106,6 +106,7 @@ xx(TK_Optional, "'optional'") xx(TK_Export, "'expert'") xx(TK_Virtual, "'virtual'") xx(TK_Super, "'super'") +xx(TK_Null, "'null'") xx(TK_Global, "'global'") xx(TK_Self, "'self'") xx(TK_Stop, "'stop'") diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index bc503d832..7687be371 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -1888,16 +1888,20 @@ bool FxBinary::ResolveLR(FCompileContext& ctx, bool castnumeric) { ValueType = TypeBool; } + else if (left->ValueType == TypeName && right->ValueType == TypeName) + { + ValueType = TypeName; + } else if (left->IsNumeric() && right->IsNumeric()) { - if (left->ValueType->GetRegType() == REGT_INT && right->ValueType->GetRegType() == REGT_INT) - { - ValueType = TypeSInt32; - } + if (left->ValueType->GetRegType() == REGT_INT && right->ValueType->GetRegType() == REGT_INT) + { + ValueType = TypeSInt32; + } else - { - ValueType = TypeFloat64; - } + { + ValueType = TypeFloat64; + } } else if (left->ValueType->GetRegType() == REGT_POINTER && left->ValueType == right->ValueType) { @@ -2395,7 +2399,7 @@ FxExpression *FxCompareEq::Resolve(FCompileContext& ctx) return NULL; } - if (!IsNumeric() && !IsPointer()) + if (!IsNumeric() && !IsPointer() && ValueType != TypeName) { ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); delete this; diff --git a/src/scripting/decorate/thingdef_parse.cpp b/src/scripting/decorate/thingdef_parse.cpp index f416d6103..bd4885c87 100644 --- a/src/scripting/decorate/thingdef_parse.cpp +++ b/src/scripting/decorate/thingdef_parse.cpp @@ -334,213 +334,6 @@ static void ParseEnum (FScanner &sc, PSymbolTable *symt, PClassActor *cls) sc.MustGetToken(';'); } -//========================================================================== -// -// ParseArgListDef -// -// Parses the argument list from a function declaration. -// -//========================================================================== - -static void ParseArgListDef(FScanner &sc, PClassActor *cls, - TArray &args, TArray &argflags) -{ - if (!sc.CheckToken(')')) - { - while (sc.TokenType != ')') - { - int flags = 0; - PType *type = NULL; - PClass *restrict = NULL; - - // Retrieve flags before type name - for (;;) - { - if (sc.CheckToken(TK_Coerce) || sc.CheckToken(TK_Native)) - { - } - else - { - break; - } - } - // Read the variable type - sc.MustGetAnyToken(); - switch (sc.TokenType) - { - case TK_Bool: - type = TypeBool; - break; - - case TK_Int: - type = TypeSInt32; - break; - - case TK_Float: - type = TypeFloat64; - break; - - case TK_Sound: type = TypeSound; break; - case TK_String: type = TypeString; break; - case TK_Name: type = TypeName; break; - case TK_State: type = TypeState; break; - case TK_Color: type = TypeColor; break; - case TK_Class: - sc.MustGetToken('<'); - sc.MustGetToken(TK_Identifier); // Get class name - restrict = PClass::FindClass(sc.String); - if (restrict == NULL) - { - sc.ScriptMessage("Unknown class type %s", sc.String); - FScriptPosition::ErrorCounter++; - } - else - { - type = NewClassPointer(restrict); - } - sc.MustGetToken('>'); - break; - case TK_Ellipsis: - // Making the final type NULL signals a varargs function. - type = NULL; - sc.MustGetToken(')'); - sc.UnGet(); - break; - default: - sc.ScriptMessage ("Unknown variable type %s", sc.TokenName(sc.TokenType, sc.String).GetChars()); - type = TypeSInt32; - FScriptPosition::ErrorCounter++; - break; - } - // Read the optional variable name - if (!sc.CheckToken(',') && !sc.CheckToken(')')) - { - sc.MustGetToken(TK_Identifier); - } - else - { - sc.UnGet(); - } - - if (sc.CheckToken('=')) - { - flags |= VARF_Optional; - FxExpression *def = ParseParameter(sc, cls, type, true); - delete def; - } - - args.Push(type); - argflags.Push(flags); - sc.MustGetAnyToken(); - if (sc.TokenType != ',' && sc.TokenType != ')') - { - sc.ScriptError ("Expected ',' or ')' but got %s instead", sc.TokenName(sc.TokenType, sc.String).GetChars()); - } - } - } - sc.MustGetToken(';'); -} - -//========================================================================== -// -// ParseFunctionDef -// -// Parses a native function's parameters and adds it to the class, -// if possible. -// -//========================================================================== - -void ParseFunctionDef(FScanner &sc, PClassActor *cls, FName funcname, - TArray &rets, DWORD funcflags) -{ - assert(cls != NULL); - - const AFuncDesc *afd; - TArray args; - TArray argflags; - TArray argnames; - - afd = FindFunction(funcname); - if (afd == NULL) - { - sc.ScriptMessage ("The function '%s' has not been exported from the executable.", funcname.GetChars()); - FScriptPosition::ErrorCounter++; - } - sc.MustGetToken('('); - - SetImplicitArgs(&args, &argflags, &argnames, cls, funcflags); - // This function will be removed once all internal classes have been ported so don't bother filling in the function's argument names, because for anything going through here they'll never be used. - ParseArgListDef(sc, cls, args, argflags); - - if (afd != NULL) - { - PFunction *sym = new PFunction(cls, funcname); - sym->AddVariant(NewPrototype(rets, args), argflags, argnames, *(afd->VMPointer), funcflags); - if (cls->Symbols.AddSymbol(sym) == NULL) - { - delete sym; - sc.ScriptMessage ("'%s' is already defined in class '%s'.", - funcname.GetChars(), cls->TypeName.GetChars()); - FScriptPosition::ErrorCounter++; - } - } -} - -//========================================================================== -// -// ParseNativeFunction -// -// Parses a non-action function declaration. -// -//========================================================================== - -static void ParseNativeFunction(FScanner &sc, PClassActor *cls) -{ - TArray rets(1); - - if (sc.LumpNum == -1 || Wads.GetLumpFile(sc.LumpNum) > 0) - { - sc.ScriptMessage ("functions can only be declared by native actors!"); - FScriptPosition::ErrorCounter++; - } - - // Read the type and make sure it's acceptable. - sc.MustGetAnyToken(); - switch (sc.TokenType) - { - case TK_Bool: - rets.Push(TypeBool); - break; - - case TK_Int: - rets.Push(TypeSInt32); - break; - - case TK_Float: - rets.Push(TypeFloat64); - break; - - case TK_State: - rets.Push(TypeState); - break; - - case TK_Void: - break; - - case TK_Identifier: - rets.Push(NewPointer(RUNTIME_CLASS(DObject))); - // Todo: Object type - sc.ScriptError("Object type variables not implemented yet!"); - break; - - default: - sc.ScriptError("Invalid return type %s", sc.String); - return; - } - sc.MustGetToken(TK_Identifier); - ParseFunctionDef(sc, cls, sc.String, rets, VARF_Method); -} - //========================================================================== // // ParseUserVariable @@ -1081,55 +874,6 @@ static void ParseActorProperty(FScanner &sc, Baggage &bag) } } -//========================================================================== -// -// ActorActionDef -// -// Parses an action function definition. A lot of this is essentially -// documentation in the declaration for when I have a proper language -// ready. -// -//========================================================================== - -static void ParseActionDef (FScanner &sc, PClassActor *cls) -{ - unsigned int error = 0; - FName funcname; - TArray rets; - - if (sc.LumpNum == -1 || Wads.GetLumpFile(sc.LumpNum) > 0) - { - sc.ScriptMessage ("Action functions can only be imported by internal class and actor definitions!"); - FScriptPosition::ErrorCounter++; - } - - sc.MustGetToken(TK_Native); - // check for a return value - do - { - if (sc.CheckToken(TK_Bool)) - { - rets.Push(TypeBool); - } - else if (sc.CheckToken(TK_Int)) - { - rets.Push(TypeSInt32); - } - else if (sc.CheckToken(TK_State)) - { - rets.Push(TypeState); - } - else if (sc.CheckToken(TK_Float)) - { - rets.Push(TypeFloat64); - } - } - while (sc.CheckToken(',')); - sc.MustGetToken(TK_Identifier); - funcname = sc.String; - ParseFunctionDef(sc, cls, funcname, rets, VARF_Method | VARF_Action); -} - //========================================================================== // // Starts a new actor definition @@ -1330,10 +1074,6 @@ static void ParseActor(FScanner &sc) { switch (sc.TokenType) { - case TK_Action: - ParseActionDef (sc, info); - break; - case TK_Const: ParseConstant (sc, &info->Symbols, info); break; @@ -1342,10 +1082,6 @@ static void ParseActor(FScanner &sc) ParseEnum (sc, &info->Symbols, info); break; - case TK_Native: - ParseNativeFunction (sc, info); - break; - case TK_Var: ParseUserVariable (sc, &info->Symbols, info); break; diff --git a/src/scripting/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index 1e10103a0..595f2a318 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -956,6 +956,13 @@ primary(X) ::= IDENTIFIER(A). expr->Type = NULL; X = expr; } +primary(X) ::= NULL(T). +{ + NEW_AST_NODE(Expression, expr, T); + expr->Operation = PEX_Null; + expr->Type = NULL; + X = expr; +} primary(X) ::= SUPER(T). { NEW_AST_NODE(Expression, expr, T); diff --git a/src/scripting/zscript/zcc_exprlist.h b/src/scripting/zscript/zcc_exprlist.h index 46a1b9c69..eeabb10e5 100644 --- a/src/scripting/zscript/zcc_exprlist.h +++ b/src/scripting/zscript/zcc_exprlist.h @@ -3,6 +3,7 @@ xx(Nil, ) xx(ID, ) xx(Super, ) +xx(Null, ) xx(Self, ) xx(ConstValue, ) xx(FuncCall, ) diff --git a/src/scripting/zscript/zcc_parser.cpp b/src/scripting/zscript/zcc_parser.cpp index 9fefa537d..48fd28f45 100644 --- a/src/scripting/zscript/zcc_parser.cpp +++ b/src/scripting/zscript/zcc_parser.cpp @@ -153,6 +153,7 @@ static void InitTokenMap() TOKENDEF (TK_Out, ZCC_OUT); TOKENDEF (TK_Optional, ZCC_OPTIONAL); TOKENDEF (TK_Super, ZCC_SUPER); + TOKENDEF (TK_Null, ZCC_NULL); TOKENDEF (TK_Self, ZCC_SELF); TOKENDEF ('~', ZCC_TILDE); TOKENDEF ('!', ZCC_BANG);