summaryrefslogtreecommitdiff
path: root/Build/source/utils/asymptote/types.cc
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2009-05-16 00:19:13 +0000
committerKarl Berry <karl@freefriends.org>2009-05-16 00:19:13 +0000
commitbab45528d65eaafe68a705dbb2a57075c7b7cbd8 (patch)
tree10b4ae2b5195c8dede153ab89359ec00f55f325f /Build/source/utils/asymptote/types.cc
parent8643d90372e9c31e0f461c15c596b60a545bd7d3 (diff)
asymptote 1.72 sources (not integrated into build yet)
git-svn-id: svn://tug.org/texlive/trunk@13110 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/utils/asymptote/types.cc')
-rw-r--r--Build/source/utils/asymptote/types.cc525
1 files changed, 525 insertions, 0 deletions
diff --git a/Build/source/utils/asymptote/types.cc b/Build/source/utils/asymptote/types.cc
new file mode 100644
index 00000000000..4b288938d79
--- /dev/null
+++ b/Build/source/utils/asymptote/types.cc
@@ -0,0 +1,525 @@
+/*****
+ * types.cc
+ * Andy Hammerlindl 2002/06/24
+ *
+ * Used by the compiler as a way to keep track of the type of a variable
+ * or expression.
+ *****/
+
+#include <cstdio>
+#include <algorithm>
+
+#include "entry.h"
+#include "types.h"
+#include "runtime.h"
+#include "access.h"
+
+namespace types {
+
+/* Base types */
+#define PRIMITIVE(name,Name,asyName) \
+ primitiveTy p##Name(ty_##name); \
+ ty *prim##Name() { return &p##Name; }
+#define PRIMERROR
+#include <primitives.h>
+#undef PRIMERROR
+#undef PRIMITIVE
+
+nullTy pNull;
+ty *primNull() { return &pNull; }
+
+array boolArray_(primBoolean());
+ty *boolArray() { return &boolArray_; }
+array IntArray_(primInt());
+ty *IntArray() { return &IntArray_; }
+array realArray_(primReal());
+ty *realArray() { return &realArray_; }
+array pairArray_(primPair());
+ty *pairArray() { return &pairArray_; }
+array tripleArray_(primTriple());
+ty *tripleArray() { return &tripleArray_; }
+array stringArray_(primString());
+ty *stringArray() { return &stringArray_; }
+array transformArray_(primTransform());
+ty *transformArray() { return &transformArray_; }
+array pathArray_(primPath());
+ty *pathArray() { return &pathArray_; }
+array penArray_(primPen());
+ty *penArray() { return &penArray_; }
+array guideArray_(primGuide());
+ty *guideArray() { return &guideArray_; }
+
+array boolArray2_(boolArray());
+ty *boolArray2() { return &boolArray2_; }
+array IntArray2_(IntArray());
+ty *IntArray2() { return &IntArray2_; }
+array realArray2_(realArray());
+ty *realArray2() { return &realArray2_; }
+array pairArray2_(pairArray());
+ty *pairArray2() { return &pairArray2_; }
+array tripleArray2_(tripleArray());
+ty *tripleArray2() { return &tripleArray2_; }
+array stringArray2_(stringArray());
+ty *stringArray2() { return &stringArray2_; }
+array pathArray2_(pathArray());
+ty *pathArray2() { return &pathArray2_; }
+array penArray2_(penArray());
+ty *penArray2() { return &penArray2_; }
+
+array boolArray3_(boolArray2());
+ty *boolArray3() { return &boolArray3_; }
+array IntArray3_(IntArray2());
+ty *IntArray3() { return &IntArray3_; }
+array realArray3_(realArray2());
+ty *realArray3() { return &realArray3_; }
+array pairArray3_(pairArray2());
+ty *pairArray3() { return &pairArray3_; }
+array tripleArray3_(tripleArray2());
+ty *tripleArray3() { return &tripleArray3_; }
+array stringArray3_(stringArray2());
+ty *stringArray3() { return &stringArray3_; }
+
+const char *names[] = {
+ "null",
+ "<structure>", "<function>", "<overloaded>",
+
+#define PRIMITIVE(name,Name,asyName) #asyName,
+#define PRIMERROR
+#include <primitives.h>
+#undef PRIMERROR
+#undef PRIMITIVE
+
+ "<array>"
+};
+
+ty::~ty()
+{}
+
+void ty::print(ostream& out) const
+{
+ out << names[kind];
+}
+
+trans::varEntry *primitiveTy::virtualField(symbol *id, signature *sig)
+{
+#define FIELD(Type, name, func) \
+ if (sig == 0 && id == symbol::trans(name)) { \
+ static trans::bltinAccess a(run::func); \
+ static trans::varEntry v(prim##Type(), &a, 0, position()); \
+ return &v; \
+ }
+
+ switch (kind) {
+ case ty_pair:
+ FIELD(Real,"x",pairXPart);
+ FIELD(Real,"y",pairYPart);
+ break;
+ case ty_triple:
+ FIELD(Real,"x",tripleXPart);
+ FIELD(Real,"y",tripleYPart);
+ FIELD(Real,"z",tripleZPart);
+ break;
+ case ty_transform:
+ FIELD(Real,"x",transformXPart);
+ FIELD(Real,"y",transformYPart);
+ FIELD(Real,"xx",transformXXPart);
+ FIELD(Real,"xy",transformXYPart);
+ FIELD(Real,"yx",transformYXPart);
+ FIELD(Real,"yy",transformYYPart);
+ break;
+ case ty_tensionSpecifier:
+ FIELD(Real,"out",tensionSpecifierOutPart);
+ FIELD(Real,"in",tensionSpecifierInPart);
+ FIELD(Boolean,"atLeast",tensionSpecifierAtleastPart);
+ break;
+ case ty_curlSpecifier:
+ FIELD(Real,"value",curlSpecifierValuePart);
+ FIELD(Int,"side",curlSpecifierSidePart);
+ break;
+ default:
+ break;
+ }
+ return 0;
+
+#undef FIELD
+}
+
+ty *ty::virtualFieldGetType(symbol *id)
+{
+ trans::varEntry *v = virtualField(id, 0);
+ return v ? v->getType() : 0;
+}
+
+trans::access *nullTy::castTo(ty *target, caster &) {
+ switch (target->kind) {
+ case ty_array: {
+ static trans::bltinAccess a(run::pushNullArray);
+ return &a;
+ }
+ case ty_record: {
+ static trans::bltinAccess a(run::pushNullRecord);
+ return &a;
+ }
+ case ty_function: {
+ static trans::bltinAccess a(run::pushNullFunction);
+ return &a;
+ }
+ default:
+ return 0;
+ }
+}
+
+trans::access *array::initializer()
+{
+ static trans::bltinAccess a(run::emptyArray);
+ return &a;
+}
+
+ty *array::pushType()
+{
+ if (pushtype == 0)
+ pushtype = new function(celltype,formal(celltype,"x"));
+
+ return pushtype;
+}
+
+ty *array::popType()
+{
+ if (poptype == 0)
+ poptype = new function(celltype);
+
+ return poptype;
+}
+
+ty *array::appendType()
+{
+ if (appendtype == 0)
+ appendtype = new function(primVoid(),formal(this,"a"));
+
+ return appendtype;
+}
+
+ty *array::insertType()
+{
+ if (inserttype == 0) {
+ function *f=new function(primVoid(),formal(primInt(),"i"));
+ f->addRest(this);
+ inserttype = f;
+ }
+
+ return inserttype;
+}
+
+ty *array::deleteType()
+{
+ if (deletetype == 0)
+ deletetype = new function(primVoid(),formal(primInt(),"i",true),
+ formal(primInt(),"j",true));
+
+ return deletetype;
+}
+
+ty *cyclicType() {
+ return new function(primVoid(),formal(primBoolean(),"b"));
+}
+
+ty *initializedType() {
+ return new function(primBoolean(),formal(primInt(),"i"));
+}
+
+ty *array::virtualFieldGetType(symbol *id)
+{
+ return
+ id == symbol::trans("cyclic") ? cyclicType() :
+ id == symbol::trans("push") ? pushType() :
+ id == symbol::trans("pop") ? popType() :
+ id == symbol::trans("append") ? appendType() :
+ id == symbol::trans("insert") ? insertType() :
+ id == symbol::trans("delete") ? deleteType() :
+ id == symbol::trans("initialized") ? initializedType() :
+ ty::virtualFieldGetType(id);
+}
+
+trans::varEntry *array::virtualField(symbol *id, signature *sig)
+{
+ if (sig == 0 && id == symbol::trans("length"))
+ {
+ static trans::bltinAccess a(run::arrayLength);
+ static trans::varEntry v(primInt(), &a, 0, position());
+ return &v;
+ }
+ if (sig == 0 && id == symbol::trans("keys"))
+ {
+ static trans::bltinAccess a(run::arrayKeys);
+ static trans::varEntry v(IntArray(), &a, 0, position());
+ return &v;
+ }
+ if (sig == 0 && id == symbol::trans("cyclicflag"))
+ {
+ static trans::bltinAccess a(run::arrayCyclicFlag);
+ static trans::varEntry v(primBoolean(), &a, 0, position());
+ return &v;
+ }
+ if (id == symbol::trans("cyclic") &&
+ equivalent(sig, cyclicType()->getSignature()))
+ {
+ static trans::bltinAccess a(run::arrayCyclic);
+ static trans::varEntry v(cyclicType(), &a, 0, position());
+ return &v;
+ }
+ if (id == symbol::trans("initialized") &&
+ equivalent(sig, initializedType()->getSignature()))
+ {
+ static trans::bltinAccess a(run::arrayInitialized);
+ static trans::varEntry v(initializedType(), &a, 0, position());
+ return &v;
+ }
+ if (id == symbol::trans("push") &&
+ equivalent(sig, pushType()->getSignature()))
+ {
+ static trans::bltinAccess a(run::arrayPush);
+ // v needs to be dynamic, as the push type differs among arrays.
+ trans::varEntry *v = new trans::varEntry(pushType(), &a, 0, position());
+
+ return v;
+ }
+ if (id == symbol::trans("pop") &&
+ equivalent(sig, popType()->getSignature()))
+ {
+ static trans::bltinAccess a(run::arrayPop);
+ // v needs to be dynamic, as the pop type differs among arrays.
+ trans::varEntry *v = new trans::varEntry(popType(), &a, 0, position());
+
+ return v;
+ }
+ if (id == symbol::trans("append") &&
+ equivalent(sig, appendType()->getSignature()))
+ {
+ static trans::bltinAccess a(run::arrayAppend);
+ // v needs to be dynamic, as the append type differs among arrays.
+ trans::varEntry *v = new trans::varEntry(appendType(), &a, 0, position());
+
+ return v;
+ }
+ if (id == symbol::trans("insert") &&
+ equivalent(sig, insertType()->getSignature()))
+ {
+ static trans::bltinAccess a(run::arrayInsert);
+ // v needs to be dynamic, as the insert type differs among arrays.
+ trans::varEntry *v = new trans::varEntry(insertType(), &a, 0, position());
+
+ return v;
+ }
+ if (id == symbol::trans("delete") &&
+ equivalent(sig, deleteType()->getSignature()))
+ {
+ static trans::bltinAccess a(run::arrayDelete);
+ // v needs to be dynamic, as the delete type differs among arrays.
+ trans::varEntry *v = new trans::varEntry(deleteType(), &a, 0, position());
+
+ return v;
+ }
+ else
+ return ty::virtualField(id, sig);
+}
+
+ostream& operator<< (ostream& out, const formal& f)
+{
+ if (f.Explicit)
+ out << "explicit ";
+ if (f.name)
+ f.t->printVar(out,f.name);
+ else
+ f.t->print(out);
+ if (f.defval)
+ out << "=<default>";
+ return out;
+}
+
+bool equivalent(formal& f1, formal& f2) {
+ // Just test the types.
+ // This will also return true for the rest parameter if both types are null.
+ // NOTE: Is this the right behavior?
+ return equivalent(f1.t,f2.t);
+}
+
+bool argumentEquivalent(formal &f1, formal& f2) {
+ if (f1.name == f2.name) {
+ if (f1.t == 0)
+ return f2.t == 0;
+ else if (f2.t == 0)
+ return false;
+
+ return f1.t->kind != ty_overloaded &&
+ f2.t->kind != ty_overloaded &&
+ equivalent(f1.t, f2.t);
+ }
+ else
+ return false;
+}
+
+ostream& operator<< (ostream& out, const signature& s)
+{
+ if (s.isOpen) {
+ out << "(<open>)";
+ return out;
+ }
+
+ out << "(";
+
+ formal_vector::const_iterator f = s.formals.begin();
+ if (f != s.formals.end()) {
+ out << *f;
+ ++f;
+ }
+ for (; f != s.formals.end(); ++f)
+ out << ", " << *f;
+
+ if (s.rest.t) {
+ if (!s.formals.empty())
+ out << " ";
+ out << "... " << s.rest;
+ }
+
+ out << ")";
+
+ return out;
+}
+
+
+// Equivalence by design does not look at the presence of default values.
+bool equivalent(signature *s1, signature *s2)
+{
+ // Handle null signature
+ if (s1 == 0)
+ return s2 == 0;
+ else if (s2 == 0)
+ return false;
+
+ // Two open signatures are always equivalent, as the formals are ignored.
+ if (s1->isOpen)
+ return s2->isOpen;
+ else if (s2->isOpen)
+ return false;
+
+ if (s1->formals.size() != s2->formals.size())
+ return false;
+
+ return std::equal(s1->formals.begin(),s1->formals.end(),s2->formals.begin(),
+ (bool (*)(formal&,formal&)) equivalent) &&
+ equivalent(s1->rest, s2->rest);
+}
+
+bool argumentEquivalent(signature *s1, signature *s2)
+{
+ // Handle null signature
+ if (s1 == 0)
+ return s2 == 0;
+ else if (s2 == 0)
+ return false;
+
+ if (s1->formals.size() != s2->formals.size())
+ return false;
+
+ return std::equal(s1->formals.begin(),s1->formals.end(),s2->formals.begin(),
+ (bool (*)(formal&,formal&)) argumentEquivalent) &&
+ argumentEquivalent(s1->rest, s2->rest);
+}
+
+size_t signature::hash() {
+ size_t x=2038;
+ for (formal_vector::iterator i=formals.begin(); i!=formals.end(); ++i)
+ x=x*0xFAEC+i->t->hash();
+
+ if (rest.t)
+ x=x*0xACED +rest.t->hash();
+
+ return x;
+}
+
+trans::access *function::initializer() {
+ static trans::bltinAccess a(run::pushNullFunction);
+ return &a;
+}
+
+#if 0
+ty *function::stripDefaults()
+{
+ function *f = new function(result);
+
+ Int n = sig.getNumFormals();
+ for (Int i = 0; i < n; ++i)
+ f->add(sig.getFormal(i), 0);
+
+ return f;
+}
+#endif
+
+// Only add a type with a signature distinct from the ones currently
+// in the overloaded type.
+void overloaded::addDistinct(ty *t, bool special)
+{
+ if (t->kind == ty_overloaded) {
+ overloaded *ot = (overloaded *)t;
+ for (ty_vector::iterator st = ot->sub.begin();
+ st != ot->sub.end();
+ ++st)
+ {
+ this->addDistinct(*st, special);
+ }
+ }
+ else {
+ for (ty_vector::iterator st = this->sub.begin();
+ st != this->sub.end();
+ ++st)
+ {
+ if (equivalent(t, *st, special))
+ return;
+ }
+
+ // Nonequivalent in signature - add it.
+ this->add(t);
+ }
+}
+
+
+ty *overloaded::signatureless()
+{
+ for(ty_vector::iterator t = sub.begin(); t != sub.end(); ++t)
+ if ((*t)->getSignature()==0)
+ return *t;
+
+ return 0;
+}
+
+bool overloaded::castable(ty *target, caster &c)
+{
+ for(ty_vector::iterator s = sub.begin(); s != sub.end(); ++s)
+ if (c.castable(target,*s))
+ return true;
+ return false;
+}
+
+bool equivalent(ty *t1, ty *t2)
+{
+ // The same pointer must point to the same type.
+ if (t1 == t2)
+ return true;
+
+ // Handle empty types (used in equating empty rest parameters).
+ if (t1 == 0 || t2 == 0)
+ return false;
+
+ // Ensure if an overloaded type is compared to a non-overloaded one, that the
+ // overloaded type's method is called.
+ if (t1->kind == ty_overloaded || t2->kind != ty_overloaded)
+ return t1->equiv(t2);
+ return t2->equiv(t1);
+}
+
+bool equivalent(ty *t1, ty *t2, bool special) {
+ return special ? equivalent(t1, t2) :
+ equivalent(t1->getSignature(), t2->getSignature());
+}
+
+} // namespace types