Commit 9958694f authored by Daniel Clifford's avatar Daniel Clifford Committed by Commit Bot

[torque] Implement implicit parameters

The implicit parameter syntax adds a second parameter list
before the explicit parameter list when declaring macros, builtins and
runtime functions:

  extern macro MyMacro(implicit a: Smi)(b: Oddball);

when calling the macro, only the formal parameters can be provided
at the call site. The implicit parameters are implicitly looked-up
by name in the scope of the call and prepended to the explicit parameter
list. The values that are found by name for each implicit parameter must
be castable the corresponding implicit parameter type:

  MyMacro(Null);  // Error, a is not defined
  ...
  const a: Smi = 0;
  MyMacro(Null);  // OK
  ...
  const a: Object = 0;
  MyMacro(Null);  // Error, a has wrong type

For external macros, builtins and runtime functions, the formal
parameter list expected on the C++ side is the concatenation of the
implicit and explicit parameter lists.

As a drive-by: fix the formatting of typeswitch statements in the
the presence of deferred-marked blocks and funky white space.

Bug: v8:7793
Change-Id: I40da8405c706d7cdeca35367c9c954d0b33f6bf4
Reviewed-on: https://chromium-review.googlesource.com/c/1270996
Commit-Queue: Daniel Clifford <danno@chromium.org>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#56555}
parent a63987a4
......@@ -14,7 +14,7 @@ module array {
const object: JSReceiver = ToObject_Inline(context, receiver);
// 2. Let len be ? ToLength(? Get(O, "length")).
const length: Number = GetLengthProperty(context, object);
const length: Number = GetLengthProperty(object);
// 3. Let relativeTarget be ? ToInteger(target).
const relativeTarget: Number = ToInteger_Inline(context, arguments[0]);
......@@ -63,18 +63,18 @@ module array {
// a. Let fromKey be ! ToString(from).
// b. Let toKey be ! ToString(to).
// c. Let fromPresent be ? HasProperty(O, fromKey).
const fromPresent: Boolean = HasProperty(context, object, from);
const fromPresent: Boolean = HasProperty(object, from);
// d. If fromPresent is true, then.
if (fromPresent == True) {
// i. Let fromVal be ? Get(O, fromKey).
const fromVal: Object = GetProperty(context, object, from);
const fromVal: Object = GetProperty(object, from);
// ii. Perform ? Set(O, toKey, fromVal, true).
SetProperty(context, object, to, fromVal);
SetProperty(object, to, fromVal);
} else {
// i. Perform ? DeletePropertyOrThrow(O, toKey).
DeleteProperty(context, object, to, kStrict);
DeleteProperty(object, to, kStrict);
}
// f. Let from be from + direction.
......
......@@ -14,12 +14,12 @@ module array {
// side-effect free and HasProperty/GetProperty do the conversion inline.
// 6b. Let kPresent be ? HasProperty(O, Pk).
const kPresent: Boolean = HasProperty_Inline(context, o, k);
const kPresent: Boolean = HasProperty_Inline(o, k);
// 6c. If kPresent is true, then
if (kPresent == True) {
// 6c. i. Let kValue be ? Get(O, Pk).
const kValue: Object = GetProperty(context, o, k);
const kValue: Object = GetProperty(o, k);
// 6c. ii. Perform ? Call(callbackfn, T, <kValue, k, O>).
Call(context, callbackfn, thisArg, kValue, k, o);
......@@ -147,7 +147,7 @@ module array {
const o: JSReceiver = ToObject_Inline(context, receiver);
// 2. Let len be ? ToLength(? Get(O, "length")).
const len: Number = GetLengthProperty(context, o);
const len: Number = GetLengthProperty(o);
// 3. If IsCallable(callbackfn) is false, throw a TypeError exception.
if (arguments.length == 0) {
......
......@@ -100,12 +100,12 @@ module array {
// 7. Repeat, while k >= 0.
while (k >= 0) {
// a. Let kPresent be ? HasProperty(O, ! ToString(k)).
const kPresent: Boolean = HasProperty(context, object, k);
const kPresent: Boolean = HasProperty(object, k);
// b. If kPresent is true, then.
if (kPresent == True) {
// i. Let elementK be ? Get(O, ! ToString(k)).
const element: Object = GetProperty(context, object, k);
const element: Object = GetProperty(object, k);
// ii. Let same be the result of performing Strict Equality Comparison
// searchElement === elementK.
......@@ -130,7 +130,7 @@ module array {
const object: JSReceiver = ToObject_Inline(context, receiver);
// 2. Let len be ? ToLength(? Get(O, "length")).
const length: Number = GetLengthProperty(context, object);
const length: Number = GetLengthProperty(object);
// 3. If len is 0, return -1.
if (length == SmiConstant(0)) return SmiConstant(-1);
......
......@@ -77,7 +77,7 @@ module array {
const object: JSReceiver = ToObject_Inline(context, receiver);
// 2. Let len be ? ToLength(? Get(O, "length")).
const length: Number = GetLengthProperty(context, object);
const length: Number = GetLengthProperty(object);
// 3. Let middle be floor(len / 2).
// 4. Let lower be 0.
......@@ -96,42 +96,42 @@ module array {
// b. Let upperP be ! ToString(upper).
// c. Let lowerP be ! ToString(lower).
// d. Let lowerExists be ? HasProperty(O, lowerP).
const lowerExists: Boolean = HasProperty(context, object, lower);
const lowerExists: Boolean = HasProperty(object, lower);
// e. If lowerExists is true, then.
if (lowerExists == True) {
// i. Let lowerValue be ? Get(O, lowerP).
lowerValue = GetProperty(context, object, lower);
lowerValue = GetProperty(object, lower);
}
// f. Let upperExists be ? HasProperty(O, upperP).
const upperExists: Boolean = HasProperty(context, object, upper);
const upperExists: Boolean = HasProperty(object, upper);
// g. If upperExists is true, then.
if (upperExists == True) {
// i. Let upperValue be ? Get(O, upperP).
upperValue = GetProperty(context, object, upper);
upperValue = GetProperty(object, upper);
}
// h. If lowerExists is true and upperExists is true, then
if (lowerExists == True && upperExists == True) {
// i. Perform ? Set(O, lowerP, upperValue, true).
SetProperty(context, object, lower, upperValue);
SetProperty(object, lower, upperValue);
// ii. Perform ? Set(O, upperP, lowerValue, true).
SetProperty(context, object, upper, lowerValue);
SetProperty(object, upper, lowerValue);
} else if (lowerExists == False && upperExists == True) {
// i. Perform ? Set(O, lowerP, upperValue, true).
SetProperty(context, object, lower, upperValue);
SetProperty(object, lower, upperValue);
// ii. Perform ? DeletePropertyOrThrow(O, upperP).
DeleteProperty(context, object, upper, kStrict);
DeleteProperty(object, upper, kStrict);
} else if (lowerExists == True && upperExists == False) {
// i. Perform ? DeletePropertyOrThrow(O, lowerP).
DeleteProperty(context, object, lower, kStrict);
DeleteProperty(object, lower, kStrict);
// ii. Perform ? Set(O, upperP, lowerValue, true).
SetProperty(context, object, upper, lowerValue);
SetProperty(object, upper, lowerValue);
}
// l. Increase lower by 1.
......
......@@ -189,22 +189,22 @@ module array {
const from: Number = actualStart + k;
// b. Let fromPresent be ? HasProperty(O, from).
const fromPresent: Boolean = HasProperty(context, o, from);
const fromPresent: Boolean = HasProperty(o, from);
// c. If fromPresent is true, then
if (fromPresent == True) {
// i. Let fromValue be ? Get(O, from).
const fromValue: Object = GetProperty(context, o, from);
const fromValue: Object = GetProperty(o, from);
// ii. Perform ? CreateDataPropertyOrThrow(A, ! ToString(k), fromValue).
CreateDataProperty(context, a, k, fromValue);
CreateDataProperty(a, k, fromValue);
}
// d. Increment k by 1.
k++;
}
// 12. Perform ? Set(A, "length", actualDeleteCount, true).
SetProperty(context, a, kLengthString, actualDeleteCount);
SetProperty(a, kLengthString, actualDeleteCount);
return a;
}
......@@ -225,20 +225,20 @@ module array {
const to: Number = k + itemCount;
// iii. Let fromPresent be ? HasProperty(O, from).
const fromPresent: Boolean = HasProperty(context, o, from);
const fromPresent: Boolean = HasProperty(o, from);
// iv. If fromPresent is true, then
if (fromPresent == True) {
// 1. Let fromValue be ? Get(O, from).
const fromValue: Object = GetProperty(context, o, from);
const fromValue: Object = GetProperty(o, from);
// 2. Perform ? Set(O, to, fromValue, true).
SetProperty(context, o, to, fromValue);
SetProperty(o, to, fromValue);
// v. Else fromPresent is false,
} else {
// 1. Perform ? DeletePropertyOrThrow(O, to).
DeleteProperty(context, o, to, kStrict);
DeleteProperty(o, to, kStrict);
}
// vi. Increase k by 1.
k++;
......@@ -250,7 +250,7 @@ module array {
// d. Repeat, while k > (len - actualDeleteCount + itemCount)
while (k > (len - actualDeleteCount + itemCount)) {
// i. Perform ? DeletePropertyOrThrow(O, ! ToString(k - 1)).
DeleteProperty(context, o, k - 1, kStrict);
DeleteProperty(o, k - 1, kStrict);
// ii. Decrease k by 1.
k--;
}
......@@ -274,20 +274,20 @@ module array {
const to: Number = k + itemCount - 1;
// iii. Let fromPresent be ? HasProperty(O, from).
const fromPresent: Boolean = HasProperty(context, o, from);
const fromPresent: Boolean = HasProperty(o, from);
// iv. If fromPresent is true, then
if (fromPresent == True) {
// 1. Let fromValue be ? Get(O, from).
const fromValue: Object = GetProperty(context, o, from);
const fromValue: Object = GetProperty(o, from);
// 2. Perform ? Set(O, to, fromValue, true).
SetProperty(context, o, to, fromValue);
SetProperty(o, to, fromValue);
// v. Else fromPresent is false,
} else {
// 1. Perform ? DeletePropertyOrThrow(O, to).
DeleteProperty(context, o, to, kStrict);
DeleteProperty(o, to, kStrict);
}
// vi. Decrease k by 1.
......@@ -334,7 +334,7 @@ module array {
if (arguments.length > 2) {
for (let e: Object of arguments [2: ]) {
// b. Perform ? Set(O, ! ToString(k), E, true).
SetProperty(context, o, k, e);
SetProperty(o, k, e);
// c. Increase k by 1.
k = k + 1;
......@@ -343,7 +343,7 @@ module array {
// 19. Perform ? Set(O, "length", len - actualDeleteCount + itemCount,
// true).
SetProperty(context, o, kLengthString, len - actualDeleteCount + itemCount);
SetProperty(o, kLengthString, len - actualDeleteCount + itemCount);
return a;
}
......@@ -355,7 +355,7 @@ module array {
const o: JSReceiver = ToObject(context, receiver);
// 2. Let len be ? ToLength(? Get(O, "length")).
const len: Number = GetLengthProperty(context, o);
const len: Number = GetLengthProperty(o);
// 3. Let relativeStart be ? ToInteger(start).
const start: Object = arguments[0];
......
......@@ -29,7 +29,7 @@ module array {
const object: JSReceiver = ToObject_Inline(context, receiver);
// 2. Let len be ? ToLength(? Get(O, "length")).
const length: Number = GetLengthProperty(context, object);
const length: Number = GetLengthProperty(object);
// 3. Let argCount be the number of actual arguments.
const argCount: Smi = Convert<Smi>(arguments.length);
......@@ -53,18 +53,18 @@ module array {
const to: Number = k + argCount - 1;
// iii. Let fromPresent be ? HasProperty(O, from).
const fromPresent: Boolean = HasProperty(context, object, from);
const fromPresent: Boolean = HasProperty(object, from);
// iv. If fromPresent is true, then
if (fromPresent == True) {
// 1. Let fromValue be ? Get(O, from).
const fromValue: Object = GetProperty(context, object, from);
const fromValue: Object = GetProperty(object, from);
// 2. Perform ? Set(O, to, fromValue, true).
SetProperty(context, object, to, fromValue);
SetProperty(object, to, fromValue);
} else {
// 1. Perform ? DeletePropertyOrThrow(O, to).
DeleteProperty(context, object, to, kStrict);
DeleteProperty(object, to, kStrict);
}
// vi. Decrease k by 1.
......@@ -79,7 +79,7 @@ module array {
// f. Repeat, while items is not empty
while (j < argCount) {
// ii .Perform ? Set(O, ! ToString(j), E, true).
SetProperty(context, object, j, arguments[Convert<intptr>(j)]);
SetProperty(object, j, arguments[Convert<intptr>(j)]);
// iii. Increase j by 1.
++j;
......@@ -88,7 +88,7 @@ module array {
// 5. Perform ? Set(O, "length", len + argCount, true).
const newLength: Number = length + argCount;
SetProperty(context, object, kLengthString, newLength);
SetProperty(object, kLengthString, newLength);
// 6. Return length + argCount.
return newLength;
......
......@@ -219,11 +219,14 @@ extern macro ToInteger_Inline(
extern macro ToLength_Inline(Context, Object): Number;
extern macro ToNumber_Inline(Context, Object): Number;
extern macro ToString_Inline(Context, Object): String;
extern macro GetProperty(Context, Object, Object): Object;
extern builtin SetProperty(Context, Object, Object, Object);
extern builtin DeleteProperty(Context, Object, Object, LanguageMode);
extern builtin HasProperty(Context, JSReceiver, Object): Boolean;
extern macro HasProperty_Inline(Context, JSReceiver, Object): Boolean;
extern macro GetProperty(implicit context: Context)(Object, Object): Object;
extern builtin SetProperty(implicit context: Context)(Object, Object, Object);
extern builtin DeleteProperty(implicit context: Context)(
Object, Object, LanguageMode);
extern builtin HasProperty(implicit context: Context)(
JSReceiver, Object): Boolean;
extern macro HasProperty_Inline(implicit context: Context)(
JSReceiver, Object): Boolean;
extern macro ThrowRangeError(Context, constexpr MessageTemplate): never;
extern macro ThrowTypeError(Context, constexpr MessageTemplate): never;
......@@ -245,7 +248,8 @@ extern builtin ToString(Context, Object): String;
extern runtime NormalizeElements(Context, JSObject);
extern runtime TransitionElementsKindWithKind(Context, JSObject, Smi);
extern runtime CreateDataProperty(Context, JSReceiver, Object, Object);
extern runtime CreateDataProperty(implicit context: Context)(
JSReceiver, Object, Object);
extern macro LoadRoot(constexpr RootIndex): Object;
extern macro StoreRoot(constexpr RootIndex, Object): Object;
......@@ -708,7 +712,8 @@ UnsafeCast<Context>(o: Object): Context {
extern macro RawCastObjectToJSArgumentsObjectWithLength(Object):
JSArgumentsObjectWithLength;
macro BranchIfJSArgumentsObjectWithLength(context: Context, o: Object): never
macro BranchIfJSArgumentsObjectWithLength(implicit context: Context)(o: Object):
never
labels True, False {
const heapObject: HeapObject = Cast<HeapObject>(o) otherwise False;
const map: Map = heapObject.map;
......@@ -720,20 +725,18 @@ macro BranchIfJSArgumentsObjectWithLength(context: Context, o: Object): never
goto True;
}
macro UnsafeCast<A: type>(context: Context, o: Object): A;
UnsafeCast<JSArgumentsObjectWithLength>(
context: Context, o: Object): JSArgumentsObjectWithLength {
assert(BranchIfJSArgumentsObjectWithLength(context, o));
macro UnsafeCast<A: type>(implicit context: Context)(o: Object): A;
UnsafeCast<JSArgumentsObjectWithLength>(implicit context: Context)(o: Object):
JSArgumentsObjectWithLength {
assert(BranchIfJSArgumentsObjectWithLength(o));
return RawCastObjectToJSArgumentsObjectWithLength(o);
}
macro Cast<A: type>(context: Context, o: Object): A
labels CastError;
Cast<JSArgumentsObjectWithLength>(context: Context, o: Object):
Cast<JSArgumentsObjectWithLength>(implicit context: Context)(o: Object):
JSArgumentsObjectWithLength
labels CastError {
if (BranchIfJSArgumentsObjectWithLength(context, o)) {
return UnsafeCast<JSArgumentsObjectWithLength>(context, o);
if (BranchIfJSArgumentsObjectWithLength(o)) {
return UnsafeCast<JSArgumentsObjectWithLength>(o);
} else {
goto CastError;
}
......@@ -999,18 +1002,20 @@ macro ToIndex(input: Object, context: Context): Number
return value;
}
macro GetLengthProperty(context: Context, o: Object): Number {
macro GetLengthProperty(implicit context: Context)(o: Object): Number {
try {
return (Cast<JSArray>(o) otherwise CheckArgs).length;
}
label CheckArgs {
const a: JSArgumentsObjectWithLength =
Cast<JSArgumentsObjectWithLength>(context, o) otherwise Slow;
const length: Object = a.length;
return Cast<Smi>(length) otherwise goto ToLength(length);
}
label Slow deferred {
goto ToLength(GetProperty(context, o, kLengthString));
typeswitch (o) {
case (a: JSArray): {
return a.length;
}
case (a: JSArgumentsObjectWithLength): {
const length: Object = a.length;
return Cast<Smi>(length) otherwise goto ToLength(length);
}
case (Object): deferred {
goto ToLength(GetProperty(o, kLengthString));
}
}
}
label ToLength(length: Object) deferred {
return ToLength_Inline(context, length);
......
......@@ -355,10 +355,19 @@ struct AssumeTypeImpossibleExpression : Expression {
struct ParameterList {
std::vector<std::string> names;
std::vector<TypeExpression*> types;
size_t implicit_count;
bool has_varargs;
std::string arguments_variable;
static ParameterList Empty() { return ParameterList{{}, {}, false, ""}; }
static ParameterList Empty() { return ParameterList{{}, {}, 0, false, ""}; }
std::vector<TypeExpression*> GetImplicitTypes() {
return std::vector<TypeExpression*>(types.begin(),
types.begin() + implicit_count);
}
std::vector<TypeExpression*> GetExplicitTypes() {
return std::vector<TypeExpression*>(types.begin() + implicit_count,
types.end());
}
};
struct BasicTypeExpression : TypeExpression {
......
......@@ -12,8 +12,23 @@ namespace internal {
namespace torque {
std::ostream& operator<<(std::ostream& os, const Callable& m) {
os << "callable " << m.name() << "(" << m.signature().parameter_types
<< "): " << *m.signature().return_type;
os << "callable " << m.name() << "(";
if (m.signature().implicit_count != 0) {
os << "implicit ";
TypeVector implicit_parameter_types(
m.signature().parameter_types.types.begin(),
m.signature().parameter_types.types.begin() +
m.signature().implicit_count);
os << implicit_parameter_types << ")(";
TypeVector explicit_parameter_types(
m.signature().parameter_types.types.begin() +
m.signature().implicit_count,
m.signature().parameter_types.types.end());
os << explicit_parameter_types;
} else {
os << m.signature().parameter_types;
}
os << "): " << *m.signature().return_type;
return os;
}
......
......@@ -220,7 +220,8 @@ void DeclarationVisitor::Visit(SpecializationDeclaration* decl) {
DeclareSpecializedTypes(key);
Signature generic_signature_with_types =
MakeSignature(generic->declaration()->callable->signature.get());
if (signature_with_types.HasSameTypesAs(generic_signature_with_types)) {
if (signature_with_types.HasSameTypesAs(generic_signature_with_types,
ParameterMode::kIgnoreImplicit)) {
if (matching_callable != nullptr) {
std::stringstream stream;
stream << "specialization of " << callable_candidate->name
......
......@@ -137,7 +137,8 @@ Macro* Declarations::TryLookupMacro(const std::string& name,
if (declarable != nullptr) {
if (declarable->IsMacroList()) {
for (auto& m : MacroList::cast(declarable)->list()) {
if (m->signature().parameter_types.types == types &&
auto signature_types = m->signature().GetExplicitTypes();
if (signature_types == types &&
!m->signature().parameter_types.var_args) {
return m;
}
......
......@@ -20,6 +20,7 @@ Signature FileVisitor::MakeSignature(const CallableNodeSignature* signature) {
Signature result{signature->parameters.names,
{GetTypeVector(signature->parameters.types),
signature->parameters.has_varargs},
signature->parameters.implicit_count,
declarations()->GetType(signature->return_type),
definition_vector};
return result;
......@@ -27,7 +28,8 @@ Signature FileVisitor::MakeSignature(const CallableNodeSignature* signature) {
Signature FileVisitor::MakeSignatureFromReturnType(
TypeExpression* return_type) {
Signature result{{}, {{}, false}, declarations()->GetType(return_type), {}};
Signature result{
{}, {{}, false}, 0, declarations()->GetType(return_type), {}};
return result;
}
......
......@@ -241,8 +241,8 @@ void ImplementationVisitor::Visit(TorqueMacroDeclaration* decl,
can_return && return_type != TypeOracle::GetVoidType();
std::string name = GetGeneratedCallableName(
decl->name, declarations()->GetCurrentSpecializationTypeNamesVector());
const TypeVector& list = signature.types();
Macro* macro = declarations()->LookupMacro(name, list);
Macro* macro =
declarations()->LookupMacro(name, signature.GetExplicitTypes());
CurrentCallableActivator activator(global_context_, macro, decl);
......@@ -1415,7 +1415,8 @@ Callable* ImplementationVisitor::LookupCall(
}
size_t caller_size = parameter_types.size();
size_t callee_size = result->signature().types().size();
size_t callee_size =
result->signature().types().size() - result->signature().implicit_count;
if (caller_size != callee_size &&
!result->signature().parameter_types.var_args) {
std::stringstream stream;
......@@ -1663,10 +1664,33 @@ VisitResult ImplementationVisitor::GenerateCall(
std::vector<VisitResult> converted_arguments;
StackRange argument_range = assembler().TopRange(0);
std::vector<std::string> constexpr_arguments;
for (size_t current = 0; current < callable->signature().implicit_count;
++current) {
std::string implicit_name = callable->signature().parameter_names[current];
if (!declarations()->TryLookup(implicit_name)) {
ReportError("implicit parameter '" + implicit_name +
"' required for call to '" + callable_name +
"' is not defined");
}
Value* val = declarations()->LookupValue(implicit_name);
VisitResult converted = GenerateImplicitConvert(
callable->signature().parameter_types.types[current], val->value());
converted_arguments.push_back(converted);
if (converted.IsOnStack()) {
argument_range.Extend(converted.stack_range());
} else {
constexpr_arguments.push_back(converted.constexpr_value());
}
}
for (size_t current = 0; current < arguments.parameters.size(); ++current) {
const Type* to_type = (current >= callable->signature().types().size())
? TypeOracle::GetObjectType()
: callable->signature().types()[current];
size_t current_after_implicit =
current + callable->signature().implicit_count;
const Type* to_type =
(current_after_implicit >= callable->signature().types().size())
? TypeOracle::GetObjectType()
: callable->signature().types()[current_after_implicit];
VisitResult converted =
GenerateImplicitConvert(to_type, arguments.parameters[current]);
converted_arguments.push_back(converted);
......@@ -1813,7 +1837,8 @@ void ImplementationVisitor::Visit(SpecializationDeclaration* decl) {
CallableNode* callable = generic->declaration()->callable;
Signature generic_signature_with_types =
MakeSignature(callable->signature.get());
if (signature_with_types.HasSameTypesAs(generic_signature_with_types)) {
if (signature_with_types.HasSameTypesAs(generic_signature_with_types,
ParameterMode::kIgnoreImplicit)) {
TypeVector specialization_types = GetTypeVector(decl->generic_parameters);
SpecializeGeneric({{generic, specialization_types},
callable,
......
......@@ -268,22 +268,37 @@ base::Optional<ParseResult> MakeUnaryOperator(
template <bool has_varargs>
base::Optional<ParseResult> MakeParameterListFromTypes(
ParseResultIterator* child_results) {
auto types = child_results->NextAs<TypeList>();
auto implicit_params =
child_results->NextAs<std::vector<NameAndTypeExpression>>();
auto explicit_types = child_results->NextAs<TypeList>();
ParameterList result;
result.types = std::move(types);
result.has_varargs = has_varargs;
result.implicit_count = implicit_params.size();
for (NameAndTypeExpression& implicit_param : implicit_params) {
if (!IsLowerCamelCase(implicit_param.name)) {
NamingConventionError("Parameter", implicit_param.name, "lowerCamelCase");
}
result.names.push_back(implicit_param.name);
result.types.push_back(implicit_param.type);
}
for (auto* explicit_type : explicit_types) {
result.types.push_back(explicit_type);
}
return ParseResult{std::move(result)};
}
template <bool has_varargs>
base::Optional<ParseResult> MakeParameterListFromNameAndTypeList(
ParseResultIterator* child_results) {
auto params = child_results->NextAs<std::vector<NameAndTypeExpression>>();
auto implicit_params =
child_results->NextAs<std::vector<NameAndTypeExpression>>();
auto explicit_params =
child_results->NextAs<std::vector<NameAndTypeExpression>>();
std::string arguments_variable = "";
if (child_results->HasNext()) {
arguments_variable = child_results->NextAs<std::string>();
}
ParameterList result;
for (NameAndTypeExpression& pair : params) {
for (NameAndTypeExpression& pair : implicit_params) {
if (!IsLowerCamelCase(pair.name)) {
NamingConventionError("Parameter", pair.name, "lowerCamelCase");
}
......@@ -291,6 +306,15 @@ base::Optional<ParseResult> MakeParameterListFromNameAndTypeList(
result.names.push_back(std::move(pair.name));
result.types.push_back(pair.type);
}
for (NameAndTypeExpression& pair : explicit_params) {
if (!IsLowerCamelCase(pair.name)) {
NamingConventionError("Parameter", pair.name, "lowerCamelCase");
}
result.names.push_back(std::move(pair.name));
result.types.push_back(pair.type);
}
result.implicit_count = implicit_params.size();
result.has_varargs = has_varargs;
result.arguments_variable = arguments_variable;
return ParseResult{std::move(result)};
......@@ -652,7 +676,6 @@ base::Optional<ParseResult> MakeTypeswitchCase(
auto name = child_results->NextAs<base::Optional<std::string>>();
auto type = child_results->NextAs<TypeExpression*>();
auto block = child_results->NextAs<Statement*>();
CheckNotDeferredStatement(block);
return ParseResult{TypeswitchCase{child_results->matched_input().pos,
std::move(name), type, block}};
}
......@@ -1044,12 +1067,19 @@ struct TorqueGrammar : Grammar {
// Result: base::Optional<TypeList>
Symbol* optionalGenericParameters = Optional<TypeList>(&genericParameters);
Symbol* optionalImplicitParameterList{
TryOrDefault<std::vector<NameAndTypeExpression>>(
Sequence({Token("("), Token("implicit"),
List<NameAndTypeExpression>(&nameAndType, Token(",")),
Token(")")}))};
// Result: ParameterList
Symbol typeListMaybeVarArgs = {
Rule({Token("("), List<TypeExpression*>(Sequence({&type, Token(",")})),
Token("..."), Token(")")},
Rule({optionalImplicitParameterList, Token("("),
List<TypeExpression*>(Sequence({&type, Token(",")})), Token("..."),
Token(")")},
MakeParameterListFromTypes<true>),
Rule({Token("("), typeList, Token(")")},
Rule({optionalImplicitParameterList, Token("("), typeList, Token(")")},
MakeParameterListFromTypes<false>)};
// Result: LabelAndTypes
......@@ -1078,14 +1108,14 @@ struct TorqueGrammar : Grammar {
// Result: ParameterList
Symbol parameterListNoVararg = {
Rule({Token("("), List<NameAndTypeExpression>(&nameAndType, Token(",")),
Token(")")},
Rule({optionalImplicitParameterList, Token("("),
List<NameAndTypeExpression>(&nameAndType, Token(",")), Token(")")},
MakeParameterListFromNameAndTypeList<false>)};
// Result: ParameterList
Symbol parameterListAllowVararg = {
Rule({&parameterListNoVararg}),
Rule({Token("("),
Rule({optionalImplicitParameterList, Token("("),
NonemptyList<NameAndTypeExpression>(&nameAndType, Token(",")),
Token(","), Token("..."), &identifier, Token(")")},
MakeParameterListFromNameAndTypeList<true>)};
......
......@@ -195,7 +195,12 @@ std::string StructType::ToExplicitString() const {
void PrintSignature(std::ostream& os, const Signature& sig, bool with_names) {
os << "(";
for (size_t i = 0; i < sig.parameter_types.types.size(); ++i) {
if (i > 0) os << ", ";
if (i == 0 && sig.implicit_count != 0) os << "implicit ";
if (sig.implicit_count > 0 && sig.implicit_count == i) {
os << ")(";
} else {
if (i > 0) os << ", ";
}
if (with_names && !sig.parameter_names.empty()) {
os << sig.parameter_names[i] << ": ";
}
......@@ -213,8 +218,7 @@ void PrintSignature(std::ostream& os, const Signature& sig, bool with_names) {
os << " labels ";
for (size_t i = 0; i < sig.labels.size(); ++i) {
if (i > 0) os << ", ";
if (with_names) os << sig.labels[i].name;
os << sig.labels[i].name;
if (sig.labels[i].types.size() > 0) os << "(" << sig.labels[i].types << ")";
}
}
......@@ -245,8 +249,15 @@ std::ostream& operator<<(std::ostream& os, const ParameterTypes& p) {
return os;
}
bool Signature::HasSameTypesAs(const Signature& other) const {
if (!(parameter_types.types == other.parameter_types.types &&
bool Signature::HasSameTypesAs(const Signature& other,
ParameterMode mode) const {
auto compare_types = GetTypes();
auto other_compare_types = other.GetTypes();
if (mode == ParameterMode::kIgnoreImplicit) {
compare_types = GetExplicitTypes();
other_compare_types = other.GetExplicitTypes();
}
if (!(compare_types == other.parameter_types.types &&
parameter_types.var_args == other.parameter_types.var_args &&
return_type == other.return_type)) {
return false;
......@@ -271,8 +282,9 @@ bool IsAssignableFrom(const Type* to, const Type* from) {
bool IsCompatibleSignature(const Signature& sig, const TypeVector& types,
const std::vector<Label*>& labels) {
auto i = sig.parameter_types.types.begin();
if (sig.parameter_types.types.size() > types.size()) return false;
auto i = sig.parameter_types.types.begin() + sig.implicit_count;
if ((sig.parameter_types.types.size() - sig.implicit_count) > types.size())
return false;
// TODO(danno): The test below is actually insufficient. The labels'
// parameters must be checked too. ideally, the named part of
// LabelDeclarationVector would be factored out so that the label count and
......
......@@ -412,13 +412,35 @@ struct ParameterTypes {
std::ostream& operator<<(std::ostream& os, const ParameterTypes& parameters);
enum class ParameterMode { kProcessImplicit, kIgnoreImplicit };
struct Signature {
Signature(NameVector n, ParameterTypes p, size_t i, const Type* r,
LabelDeclarationVector l)
: parameter_names(std::move(n)),
parameter_types(std::move(p)),
implicit_count(i),
return_type(r),
labels(std::move(l)) {}
Signature() : implicit_count(0), return_type(nullptr) {}
const TypeVector& types() const { return parameter_types.types; }
NameVector parameter_names;
ParameterTypes parameter_types;
size_t implicit_count;
const Type* return_type;
LabelDeclarationVector labels;
bool HasSameTypesAs(const Signature& other) const;
bool HasSameTypesAs(
const Signature& other,
ParameterMode mode = ParameterMode::kProcessImplicit) const;
const TypeVector& GetTypes() const { return parameter_types.types; }
TypeVector GetImplicitTypes() const {
return TypeVector(parameter_types.types.begin(),
parameter_types.types.begin() + implicit_count);
}
TypeVector GetExplicitTypes() const {
return TypeVector(parameter_types.types.begin() + implicit_count,
parameter_types.types.end());
}
};
struct Arguments {
......
......@@ -127,7 +127,7 @@ module array {
builtin Load<ElementsAccessor: type>(
context: Context, sortState: FixedArray, elements: HeapObject,
index: Smi): Object {
return GetProperty(context, elements, index);
return GetProperty(elements, index);
}
Load<FastPackedSmiElements>(
......@@ -196,7 +196,7 @@ module array {
builtin Store<ElementsAccessor: type>(
context: Context, sortState: FixedArray, elements: HeapObject, index: Smi,
value: Object): Smi {
SetProperty(context, elements, index, value);
SetProperty(elements, index, value);
return kSuccess;
}
......@@ -546,13 +546,13 @@ module array {
// Used for OOB asserts in Copy* builtins.
macro GetReceiverLengthProperty(
context: Context, sortState: FixedArray): Smi {
implicit context: Context)(sortState: FixedArray): Smi {
const receiver: JSReceiver = GetReceiver(sortState);
if (IsJSArray(receiver)) return UnsafeCast<JSArray>(receiver).length_fast;
const len: Number =
ToLength_Inline(context, GetProperty(context, receiver, kLengthString));
ToLength_Inline(context, GetProperty(receiver, kLengthString));
return UnsafeCast<Smi>(len);
}
......@@ -563,7 +563,7 @@ module array {
labels Bailout {
assert(srcPos >= 0);
assert(dstPos >= 0);
assert(srcPos <= GetReceiverLengthProperty(context, sortState) - length);
assert(srcPos <= GetReceiverLengthProperty(sortState) - length);
assert(dstPos <= tempArray.length - length);
let srcIdx: Smi = srcPos;
......@@ -584,7 +584,7 @@ module array {
assert(srcPos >= 0);
assert(dstPos >= 0);
assert(srcPos <= tempArray.length - length);
assert(dstPos <= GetReceiverLengthProperty(context, sortState) - length);
assert(dstPos <= GetReceiverLengthProperty(sortState) - length);
let store: StoreFn = GetStoreFn(sortState);
......@@ -610,8 +610,8 @@ module array {
srcPos: Smi, dstPos: Smi, length: Smi): Smi {
assert(srcPos >= 0);
assert(dstPos >= 0);
assert(srcPos <= GetReceiverLengthProperty(context, sortState) - length);
assert(dstPos <= GetReceiverLengthProperty(context, sortState) - length);
assert(srcPos <= GetReceiverLengthProperty(sortState) - length);
assert(dstPos <= GetReceiverLengthProperty(sortState) - length);
try {
let load: LoadFn = GetLoadFn(sortState);
......@@ -1773,7 +1773,7 @@ module array {
}
label Slow {
// 3. Let len be ? ToLength(? Get(obj, "length")).
const len: Number = GetLengthProperty(context, obj);
const len: Number = GetLengthProperty(obj);
if (len < 2) return receiver;
const nofNonUndefined: Smi = PrepareElementsForSort(context, obj, len);
......
......@@ -16,11 +16,19 @@ def preprocess(input):
input = re.sub(r'(\)\s*\:\s*\S+\s+)labels\s+',
r'\1,\n/*_LABELS_HOLD_*/ ', input)
input = re.sub(r'(\s+)operator\s*(\'[^\']+\')', r'\1/*_OPE \2*/', input)
# Mangle typeswitches to look like switch statements with the extra type
# information and syntax encoded in comments.
input = re.sub(r'(\s+)typeswitch\s*\(', r'\1/*_TYPE*/switch (', input)
input = re.sub(r'(\s+)case\s*\(([^\s]+)\s+\:\s*([^\:]+)\)(\s*)\:',
r'\1case \3: /*_TSV\2:*/', input)
input = re.sub(r'(\s+)case\s*\(([^\:]+)\)(\s*)\:',
input = re.sub(r'(\s+)case\s*\(\s*([^\:]+)\s*\)(\s*)\:\s*deferred',
r'\1case \2: /*_TSXDEFERRED_*/', input)
input = re.sub(r'(\s+)case\s*\(\s*([^\:]+)\s*\)(\s*)\:',
r'\1case \2: /*_TSX*/', input)
input = re.sub(r'(\s+)case\s*\(\s*([^\s]+)\s*\:\s*([^\:]+)\s*\)(\s*)\:\s*deferred',
r'\1case \3: /*_TSVDEFERRED_\2:*/', input)
input = re.sub(r'(\s+)case\s*\(\s*([^\s]+)\s*\:\s*([^\:]+)\s*\)(\s*)\:',
r'\1case \3: /*_TSV\2:*/', input)
input = re.sub(r'\sgenerates\s+\'([^\']+)\'\s*',
r' _GeNeRaTeS00_/*\1@*/', input)
input = re.sub(r'\sconstexpr\s+\'([^\']+)\'\s*',
......@@ -37,8 +45,12 @@ def postprocess(output):
output = re.sub(r',([\n ]*)\/\*_LABELS_HOLD_\*\/', r'\1labels', output)
output = re.sub(r'\/\*_OPE \'([^\']+)\'\*\/', r"operator '\1'", output)
output = re.sub(r'\/\*_TYPE\*\/(\s*)switch', r'typeswitch', output)
output = re.sub(r'case ([^\:]+)\:\s*\/\*_TSXDEFERRED_\*\/',
r'case (\1): deferred', output)
output = re.sub(r'case ([^\:]+)\:\s*\/\*_TSX\*\/',
r'case (\1):', output)
output = re.sub(r'case ([^\:]+)\:\s*\/\*_TSVDEFERRED_([^\:]+)\:\*\/',
r'case (\2: \1): deferred', output)
output = re.sub(r'case ([^\:]+)\:\s*\/\*_TSV([^\:]+)\:\*\/',
r'case (\2: \1):', output)
output = re.sub(r'\n_GeNeRaTeS00_\s*\/\*([^@]+)@\*\/',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment