extended scripting extensions to code segment 3 (instructions and functions with optional arguments)

actorid
Marc Zinnschlag 15 years ago
parent b3cc3073a3
commit c18e83d7c0

@ -346,9 +346,10 @@ namespace Compiler
start(); start();
mTokenLoc = loc; mTokenLoc = loc;
parseArguments (argumentType, scanner); int optionals = parseArguments (argumentType, scanner);
extensions->generateFunctionCode (keyword, mCode, mLiterals, mExplicit); extensions->generateFunctionCode (keyword, mCode, mLiterals, mExplicit,
optionals);
mOperands.push_back (returnType); mOperands.push_back (returnType);
mExplicit.clear(); mExplicit.clear();
mRefOp = false; mRefOp = false;
@ -465,9 +466,9 @@ namespace Compiler
if (extensions->isFunction (keyword, returnType, argumentType, false)) if (extensions->isFunction (keyword, returnType, argumentType, false))
{ {
mTokenLoc = loc; mTokenLoc = loc;
parseArguments (argumentType, scanner); int optionals = parseArguments (argumentType, scanner);
extensions->generateFunctionCode (keyword, mCode, mLiterals, ""); extensions->generateFunctionCode (keyword, mCode, mLiterals, "", optionals);
mOperands.push_back (returnType); mOperands.push_back (returnType);
mNextOperand = false; mNextOperand = false;

@ -53,48 +53,77 @@ namespace Compiler
} }
void Extensions::registerFunction (const std::string& keyword, char returnType, void Extensions::registerFunction (const std::string& keyword, char returnType,
const std::string& argumentType, int segment5code, int segment5codeExplicit) const std::string& argumentType, int code, int codeExplicit)
{ {
assert (segment5code>=33554432 && segment5code<=67108863); Function function;
if (argumentType.find ('/')==std::string::npos)
{
function.mSegment = 5;
assert (code>=33554432 && code<=67108863);
assert (codeExplicit==-1 || (codeExplicit>=33554432 && codeExplicit<=67108863));
}
else
{
function.mSegment = 3;
assert (code>=0x20000 && code<=0x2ffff);
assert (codeExplicit==-1 || (codeExplicit>=0x20000 && codeExplicit<=0x2ffff));
}
int code = mNextKeywordIndex--; int keywordIndex = mNextKeywordIndex--;
mKeywords.insert (std::make_pair (keyword, code)); mKeywords.insert (std::make_pair (keyword, keywordIndex));
Function function;
function.mReturn = returnType; function.mReturn = returnType;
function.mArguments = argumentType; function.mArguments = argumentType;
function.mCode = segment5code; function.mCode = code;
function.mCodeExplicit = segment5codeExplicit; function.mCodeExplicit = codeExplicit;
mFunctions.insert (std::make_pair (code, function)); mFunctions.insert (std::make_pair (keywordIndex, function));
} }
void Extensions::registerInstruction (const std::string& keyword, void Extensions::registerInstruction (const std::string& keyword,
const std::string& argumentType, int segment5code, int segment5codeExplicit) const std::string& argumentType, int code, int codeExplicit)
{ {
assert (segment5code>=33554432 && segment5code<=67108863); Instruction instruction;
int code = mNextKeywordIndex--; if (argumentType.find ('/')==std::string::npos)
{
instruction.mSegment = 5;
assert (code>=33554432 && code<=67108863);
assert (codeExplicit==-1 || (codeExplicit>=33554432 && codeExplicit<=67108863));
}
else
{
instruction.mSegment = 3;
assert (code>=0x20000 && code<=0x2ffff);
assert (codeExplicit==-1 || (codeExplicit>=0x20000 && codeExplicit<=0x2ffff));
}
mKeywords.insert (std::make_pair (keyword, code)); int keywordIndex = mNextKeywordIndex--;
mKeywords.insert (std::make_pair (keyword, keywordIndex));
Instruction instruction;
instruction.mArguments = argumentType; instruction.mArguments = argumentType;
instruction.mCode = segment5code; instruction.mCode = code;
instruction.mCodeExplicit = segment5codeExplicit; instruction.mCodeExplicit = codeExplicit;
mInstructions.insert (std::make_pair (code, instruction)); mInstructions.insert (std::make_pair (keywordIndex, instruction));
} }
void Extensions::generateFunctionCode (int keyword, std::vector<Interpreter::Type_Code>& code, void Extensions::generateFunctionCode (int keyword, std::vector<Interpreter::Type_Code>& code,
Literals& literals, const std::string& id) const Literals& literals, const std::string& id, int optionalArguments) const
{ {
assert (optionalArguments>=0);
std::map<int, Function>::const_iterator iter = mFunctions.find (keyword); std::map<int, Function>::const_iterator iter = mFunctions.find (keyword);
if (iter==mFunctions.end()) if (iter==mFunctions.end())
throw std::logic_error ("unknown custom function keyword"); throw std::logic_error ("unknown custom function keyword");
if (optionalArguments && iter->second.mSegment!=3)
throw std::logic_error ("functions with optional arguments must be placed into segment 3");
if (!id.empty()) if (!id.empty())
{ {
if (iter->second.mCodeExplicit==-1) if (iter->second.mCodeExplicit==-1)
@ -104,19 +133,46 @@ namespace Compiler
Generator::pushInt (code, literals, index); Generator::pushInt (code, literals, index);
} }
code.push_back (Generator::segment5 ( switch (iter->second.mSegment)
id.empty() ? iter->second.mCode : iter->second.mCodeExplicit)); {
case 3:
if (optionalArguments>=256)
throw std::logic_error ("number of optional arguments is too large for segment 3");
code.push_back (Generator::segment3 (
id.empty() ? iter->second.mCode : iter->second.mCodeExplicit,
optionalArguments));
break;
case 5:
code.push_back (Generator::segment5 (
id.empty() ? iter->second.mCode : iter->second.mCodeExplicit));
break;
default:
throw std::logic_error ("unsupported code segment");
}
} }
void Extensions::generateInstructionCode (int keyword, void Extensions::generateInstructionCode (int keyword,
std::vector<Interpreter::Type_Code>& code, Literals& literals, const std::string& id) std::vector<Interpreter::Type_Code>& code, Literals& literals, const std::string& id,
const int optionalArguments) const
{ {
assert (optionalArguments>=0);
std::map<int, Instruction>::const_iterator iter = mInstructions.find (keyword); std::map<int, Instruction>::const_iterator iter = mInstructions.find (keyword);
if (iter==mInstructions.end()) if (iter==mInstructions.end())
throw std::logic_error ("unknown custom instruction keyword"); throw std::logic_error ("unknown custom instruction keyword");
if (optionalArguments && iter->second.mSegment!=3)
throw std::logic_error ("instructions with optional arguments must be placed into segment 3");
if (!id.empty()) if (!id.empty())
{ {
if (iter->second.mCodeExplicit==-1) if (iter->second.mCodeExplicit==-1)
@ -126,7 +182,29 @@ namespace Compiler
Generator::pushInt (code, literals, index); Generator::pushInt (code, literals, index);
} }
code.push_back (Generator::segment5 ( switch (iter->second.mSegment)
id.empty() ? iter->second.mCode : iter->second.mCodeExplicit)); {
case 3:
if (optionalArguments>=256)
throw std::logic_error ("number of optional arguments is too large for segment 3");
code.push_back (Generator::segment3 (
id.empty() ? iter->second.mCode : iter->second.mCodeExplicit,
optionalArguments));
break;
case 5:
code.push_back (Generator::segment5 (
id.empty() ? iter->second.mCode : iter->second.mCodeExplicit));
break;
default:
throw std::logic_error ("unsupported code segment");
}
} }
} }

@ -21,6 +21,7 @@ namespace Compiler
std::string mArguments; std::string mArguments;
int mCode; int mCode;
int mCodeExplicit; int mCodeExplicit;
int mSegment;
}; };
struct Instruction struct Instruction
@ -28,6 +29,7 @@ namespace Compiler
std::string mArguments; std::string mArguments;
int mCode; int mCode;
int mCodeExplicit; int mCodeExplicit;
int mSegment;
}; };
int mNextKeywordIndex; int mNextKeywordIndex;
@ -54,30 +56,29 @@ namespace Compiler
///< Is this keyword registered with a function? If yes, return argument types. ///< Is this keyword registered with a function? If yes, return argument types.
void registerFunction (const std::string& keyword, char returnType, void registerFunction (const std::string& keyword, char returnType,
const std::string& argumentType, int segment5code, int segment5codeExplicit = -1); const std::string& argumentType, int code, int codeExplicit = -1);
///< Register a custom function ///< Register a custom function
/// - keyword must be all lower case. /// - keyword must be all lower case.
/// - keyword must be unique /// - keyword must be unique
/// - if explicit references are not supported, segment5codeExplicit must be set to -1 /// - if explicit references are not supported, segment5codeExplicit must be set to -1
/// \note Currently only segment 5 opcodes are supported. /// \note Currently only segment 3 and segment 5 opcodes are supported.
void registerInstruction (const std::string& keyword, void registerInstruction (const std::string& keyword,
const std::string& argumentType, int segment5code, int segment5codeExplicit = -1); const std::string& argumentType, int code, int codeExplicit = -1);
///< Register a custom instruction ///< Register a custom instruction
/// - keyword must be all lower case. /// - keyword must be all lower case.
/// - keyword must be unique /// - keyword must be unique
/// - if explicit references are not supported, segment5codeExplicit must be set to -1 /// - if explicit references are not supported, segment5codeExplicit must be set to -1
/// \note Currently only segment 5 opcodes are supported. /// \note Currently only segment 3 and segment 5 opcodes are supported.
void generateFunctionCode (int keyword, std::vector<Interpreter::Type_Code>& code, void generateFunctionCode (int keyword, std::vector<Interpreter::Type_Code>& code,
Literals& literals, const std::string& id) const; Literals& literals, const std::string& id, int optionalArguments) const;
///< Append code for function to \a code. ///< Append code for function to \a code.
void generateInstructionCode (int keyword, std::vector<Interpreter::Type_Code>& code, void generateInstructionCode (int keyword, std::vector<Interpreter::Type_Code>& code,
Literals& literals, const std::string& id) const; Literals& literals, const std::string& id, int optionalArguments) const;
///< Append code for function to \a code. ///< Append code for function to \a code.
}; };
} }
#endif #endif

@ -242,9 +242,9 @@ namespace Compiler
if (extensions->isInstruction (keyword, argumentType, mState==ExplicitState)) if (extensions->isInstruction (keyword, argumentType, mState==ExplicitState))
{ {
mExprParser.parseArguments (argumentType, scanner, mCode, true); int optionals = mExprParser.parseArguments (argumentType, scanner, mCode, true);
extensions->generateInstructionCode (keyword, mCode, mLiterals, mExplicit); extensions->generateInstructionCode (keyword, mCode, mLiterals, mExplicit, optionals);
mState = EndState; mState = EndState;
return true; return true;
} }

Loading…
Cancel
Save