-/* Cycript - Optimizing JavaScript Compiler/Runtime
- * Copyright (C) 2009-2015 Jay Freeman (saurik)
+/* Cycript - The Truly Universal Scripting Language
+ * Copyright (C) 2009-2016 Jay Freeman (saurik)
*/
/* GNU Affero General Public License, Version 3 {{{ */
}
CYTarget *CYArray::Replace(CYContext &context) {
- if (elements_ != NULL)
- elements_->Replace(context);
+ CYForEach (element, elements_)
+ element->Replace(context);
return this;
}
}
CYExpression *CYAssignment::Replace(CYContext &context) {
+ // XXX: this is a horrible hack but I'm a month over schedule :(
+ if (CYSubscriptMember *subscript = dynamic_cast<CYSubscriptMember *>(lhs_))
+ return $C2($M(subscript->object_, $S("$cys")), subscript->property_, rhs_);
context.Replace(lhs_);
context.Replace(rhs_);
return this;
if (tail_->constructor_ == NULL)
tail_->constructor_ = $ CYFunctionExpression(NULL, NULL, NULL);
+ tail_->constructor_->name_ = name_;
tail_->constructor_ = CYSuperize(context, tail_->constructor_);
context.super_ = old;
void CYElementValue::Replace(CYContext &context) {
context.Replace(value_);
- if (next_ != NULL)
- next_->Replace(context);
}
CYForInitializer *CYEmpty::Replace(CYContext &context) {
return NULL;
}
-CYStatement *CYExternal::Replace(CYContext &context) {
- return $E($ CYAssign($V(typed_->identifier_), $C1(typed_->Replace(context), $C2($V("dlsym"), $V("RTLD_DEFAULT"), $S(typed_->identifier_->Word())))));
+CYTarget *CYExtend::Replace(CYContext &context) {
+ return object_.Replace(context, lhs_);
+}
+
+CYStatement *CYExternalDefinition::Replace(CYContext &context) {
+ return $E($ CYAssign($V(name_), $ CYExternalExpression(abi_, type_, name_)));
+}
+
+CYTarget *CYExternalExpression::Replace(CYContext &context) {
+ return $C1(type_->Replace(context), $C2($V("dlsym"), $V("RTLD_DEFAULT"), name_->PropertyName(context)));
}
CYNumber *CYFalse::Number(CYContext &context) {
return $ CYVar($B1($B($I(module_->part_->Word()), $C1($V("require"), module_->Replace(context, "/")))));
}
+CYStatement *CYImportDeclaration::Replace(CYContext &context) {
+ CYIdentifier *module(context.Unique());
+
+ CYList<CYStatement> statements;
+ CYForEach (specifier, specifiers_)
+ statements->*specifier->Replace(context, module);
+
+ return $ CYBlock($$
+ ->* $ CYLexical(false, $B1($B(module, $C1($V("require"), module_))))
+ ->* statements);
+}
+
+CYStatement *CYImportSpecifier::Replace(CYContext &context, CYIdentifier *module) {
+ binding_ = binding_->Replace(context, CYIdentifierLexical);
+
+ CYExpression *import($V(module));
+ if (name_ != NULL)
+ import = $M(import, $S(name_));
+ return $E($ CYAssign($V(binding_), import));
+}
+
CYTarget *CYIndirect::Replace(CYContext &context) {
return $M(rhs_, $S("$cyi"));
}
return String(context);
}
-CYTarget *CYObject::Replace(CYContext &context) {
+CYTarget *CYObject::Replace(CYContext &context, CYTarget *seed) {
CYBuilder builder;
if (properties_ != NULL)
- properties_ = properties_->ReplaceAll(context, builder, $ CYThis(), false);
+ properties_ = properties_->ReplaceAll(context, builder, $ CYThis(), seed != this);
if (builder) {
return $C1($M($ CYFunctionExpression(NULL, builder.bindings_->Parameter(context),
builder.statements_
->* $ CYReturn($ CYThis())
- ), $S("call")), this, builder.bindings_->Argument(context));
+ ), $S("call")), seed, builder.bindings_->Argument(context));
}
CYForEach (property, properties_)
property->Replace(context);
- return this;
+ return seed;
+}
+
+CYTarget *CYObject::Replace(CYContext &context) {
+ return Replace(context, this);
}
CYTarget *CYParenthetical::Replace(CYContext &context) {
}
}
+CYTarget *CYResolveMember::Replace(CYContext &context) {
+ return $M($M(object_, $S("$cyr")), property_);
+}
+
CYStatement *CYReturn::Replace(CYContext &context) {
if (context.nonlocal_ != NULL) {
CYProperty *value(value_ == NULL ? NULL : $ CYPropertyValue($S("$cyv"), value_));
}
CYTarget *CYRubyBlock::Replace(CYContext &context) {
- return call_->AddArgument(context, proc_->Replace(context));
+ return lhs_->AddArgument(context, proc_->Replace(context));
}
CYTarget *CYRubyBlock::AddArgument(CYContext &context, CYExpression *value) {
else if (existing->kind_ == CYIdentifierGlobal || existing->kind_ == CYIdentifierMagic)
existing->kind_ = kind;
else if (existing->kind_ == CYIdentifierLexical || kind == CYIdentifierLexical)
- _assert(false); // XXX: throw new SyntaxError()
+ _assert(false);
+ else if (transparent_ && existing->kind_ == CYIdentifierArgument && kind == CYIdentifierVariable)
+ _assert(false);
+ // XXX: throw new SyntaxError() instead of these asserts
return existing;
}
CYForEach (i, internal_) {
_assert(i->identifier_->next_ == i->identifier_);
switch (i->kind_) {
- case CYIdentifierArgument: {
- _assert(!transparent_);
- } break;
-
case CYIdentifierLexical: {
if (!damaged_) {
CYIdentifier *replace(context.Unique());
default:; } }
}
+CYTarget *CYSubscriptMember::Replace(CYContext &context) {
+ return $C1($M(object_, $S("$cyg")), property_);
+}
+
CYElementValue *CYSpan::Replace(CYContext &context) { $T(NULL)
return $ CYElementValue(expression_, $ CYElementValue(string_, next_->Replace(context)));
}
return $S(value, size);
}
+CYIdentifier *CYString::Identifier() const {
+ if (const char *word = Word())
+ return $ CYIdentifier(word);
+ return NULL;
+}
+
CYNumber *CYString::Number(CYContext &context) {
// XXX: there is a precise algorithm for this
return NULL;
return this;
}
+CYStatement *CYStructDefinition::Replace(CYContext &context) {
+ CYTarget *target(tail_->Replace(context));
+ if (name_ != NULL)
+ target = $C1($M(target, $S("withName")), $S(name_->Word()));
+ return $ CYLexical(false, $B1($B($I($pool.strcat(name_->Word(), "$cy", NULL)), target)));
+}
+
+CYTarget *CYStructTail::Replace(CYContext &context) {
+ CYList<CYElementValue> types;
+ CYList<CYElementValue> names;
+
+ CYForEach (field, fields_) {
+ types->*$ CYElementValue(field->type_->Replace(context));
+
+ CYExpression *name;
+ if (field->name_ == NULL)
+ name = NULL;
+ else
+ name = field->name_->PropertyName(context);
+ names->*$ CYElementValue(name);
+ }
+
+ return $N2($V("Type"), $ CYArray(types), $ CYArray(names));
+}
+
CYTarget *CYSuperAccess::Replace(CYContext &context) {
return $C1($M($M($M($V(context.super_), $S("prototype")), property_), $S("bind")), $ CYThis());
}
return $C($C1($M($V(context.super_), $S("bind")), $ CYThis()), arguments_);
}
+CYTarget *CYSymbol::Replace(CYContext &context) {
+ return $C1($M($V("Symbol"), $S("for")), $S(name_));
+}
+
CYStatement *CYSwitch::Replace(CYContext &context) {
context.Replace(value_);
clauses_->Replace(context);
return next_->Replace(context, $ CYCall($ CYDirectMember(type, $ CYString("blockWith")), parameters_->Argument(context)));
}
+CYTarget *CYTypeCharacter::Replace(CYContext &context) {
+ switch (signing_) {
+ case CYTypeNeutral: return $V("char");
+ case CYTypeSigned: return $V("schar");
+ case CYTypeUnsigned: return $V("uchar");
+ default: _assert(false);
+ }
+}
+
CYTarget *CYTypeConstant::Replace_(CYContext &context, CYTarget *type) {
return next_->Replace(context, $ CYCall($ CYDirectMember(type, $ CYString("constant"))));
}
CYStatement *CYTypeDefinition::Replace(CYContext &context) {
- CYIdentifier *identifier(typed_->identifier_);
- typed_->identifier_ = NULL;
- return $ CYLexical(false, $B1($B(identifier, $ CYTypeExpression(typed_))));
+ return $ CYLexical(false, $B1($B(name_, $ CYTypeExpression(type_))));
+}
+
+CYTarget *CYTypeEnum::Replace(CYContext &context) {
+ CYList<CYProperty> properties;
+ CYForEach (constant, constants_)
+ properties->*$ CYPropertyValue($S(constant->name_->Word()), constant->value_);
+ CYObject *constants($ CYObject(properties));
+
+ if (specifier_ == NULL)
+ return $N1($V("Type"), constants);
+ else
+ return $C1($M(specifier_->Replace(context), $S("enumFor")), constants);
}
CYTarget *CYTypeError::Replace(CYContext &context) {
return typed_->Replace(context);
}
+CYTarget *CYTypeInt128::Replace(CYContext &context) {
+ return $V(signing_ == CYTypeUnsigned ? "uint128" : "int128");
+}
+
+CYTarget *CYTypeIntegral::Replace(CYContext &context) {
+ bool u(signing_ == CYTypeUnsigned);
+ switch (length_) {
+ case 0: return $V(u ? "ushort" : "short");
+ case 1: return $V(u ? "uint" : "int");
+ case 2: return $V(u ? "ulong" : "long");
+ case 3: return $V(u ? "ulonglong" : "longlong");
+ default: _assert(false);
+ }
+}
+
CYTarget *CYTypeModifier::Replace(CYContext &context, CYTarget *type) { $T(type)
return Replace_(context, type);
}
CYTarget *CYTypeFunctionWith::Replace_(CYContext &context, CYTarget *type) {
- return next_->Replace(context, $ CYCall($ CYDirectMember(type, $ CYString("functionWith")), parameters_->Argument(context)));
-}
-
-CYTarget *CYTypeLong::Replace(CYContext &context) {
- return $ CYCall($ CYDirectMember(specifier_->Replace(context), $ CYString("long")));
+ CYList<CYArgument> arguments(parameters_->Argument(context));
+ if (variadic_)
+ arguments->*$C_($ CYNull());
+ return next_->Replace(context, $ CYCall($ CYDirectMember(type, $ CYString("functionWith")), arguments));
}
CYTarget *CYTypePointerTo::Replace_(CYContext &context, CYTarget *type) {
return next_->Replace(context, $ CYCall($ CYDirectMember(type, $ CYString("pointerTo"))));
}
-CYTarget *CYTypeShort::Replace(CYContext &context) {
- return $ CYCall($ CYDirectMember(specifier_->Replace(context), $ CYString("short")));
-}
+CYTarget *CYTypeReference::Replace(CYContext &context) {
+ const char *prefix;
+ switch (kind_) {
+ case CYTypeReferenceStruct: prefix = "$cys"; break;
+ case CYTypeReferenceEnum: prefix = "$cye"; break;
+ default: _assert(false);
+ }
-CYTarget *CYTypeSigned::Replace(CYContext &context) {
- return $ CYCall($ CYDirectMember(specifier_->Replace(context), $ CYString("signed")));
+ return $V($pool.strcat(prefix, name_->Word(), NULL));
}
CYTarget *CYTypeStruct::Replace(CYContext &context) {
- CYList<CYElementValue> types;
- CYList<CYElementValue> names;
-
- CYForEach (field, fields_) {
- CYTypedIdentifier *typed(field->typed_);
- types->*$ CYElementValue(typed->Replace(context));
-
- CYExpression *name;
- if (typed->identifier_ == NULL)
- name = NULL;
- else
- name = $S(typed->identifier_->Word());
- names->*$ CYElementValue(name);
- }
-
- CYTarget *target($N2($V("Type"), $ CYArray(types), $ CYArray(names)));
+ CYTarget *target(tail_->Replace(context));
if (name_ != NULL)
target = $C1($M(target, $S("withName")), $S(name_->Word()));
return target;
}
-CYTarget *CYTypeUnsigned::Replace(CYContext &context) {
- return $ CYCall($ CYDirectMember(specifier_->Replace(context), $ CYString("unsigned")));
-}
-
CYTarget *CYTypeVariable::Replace(CYContext &context) {
return $V(name_);
}
return next_->Replace(context, $ CYCall($ CYDirectMember(type, $ CYString("volatile"))));
}
-CYTarget *CYTypedIdentifier::Replace(CYContext &context) {
+CYTarget *CYType::Replace(CYContext &context) {
return modifier_->Replace(context, specifier_->Replace(context));
}
-CYTypeFunctionWith *CYTypedIdentifier::Function() {
- CYTypeModifier **modifier(&modifier_);
- if (*modifier == NULL)
+CYTypeFunctionWith *CYType::Function() {
+ CYTypeModifier *&modifier(CYGetLast(modifier_));
+ if (modifier == NULL)
return NULL;
- while ((*modifier)->next_ != NULL)
- modifier = &(*modifier)->next_;
- CYTypeFunctionWith *function((*modifier)->Function());
+
+ CYTypeFunctionWith *function(modifier->Function());
if (function == NULL)
return NULL;
- *modifier = NULL;
+
+ modifier = NULL;
return function;
}
CYArgument *CYTypedParameter::Argument(CYContext &context) { $T(NULL)
- return $ CYArgument(typed_->Replace(context), next_->Argument(context));
+ return $ CYArgument(type_->Replace(context), next_->Argument(context));
}
CYFunctionParameter *CYTypedParameter::Parameters(CYContext &context) { $T(NULL)
- return $ CYFunctionParameter($ CYBinding(typed_->identifier_ ?: context.Unique()), next_->Parameters(context));
+ return $ CYFunctionParameter($ CYBinding(name_ ?: context.Unique()), next_->Parameters(context));
}
CYExpression *CYTypedParameter::TypeSignature(CYContext &context, CYExpression *prefix) { $T(prefix)
- return next_->TypeSignature(context, $ CYAdd(prefix, typed_->Replace(context)));
+ return next_->TypeSignature(context, $ CYAdd(prefix, type_->Replace(context)));
}
CYForInitializer *CYVar::Replace(CYContext &context) {