Hi all,

I'm looking for a review on the addition of PRIM_QUERY_TYPE and PRIM_QUERY_PARAM to the compiler. These functions allow access to the generic instantiation of a record or class type's param and type fields without requiring a specific instantiation of the type itself. For instance,

class R {
  param foo = int(64);
}

type t = R(5);

can access the value of t's foo field without having to create

var baz: t;

These functions are useful for my ongoing initialization rework, but could be committed and tested separately. Full description of use is in the commit message.

Thanks,
Lydia Duncan
Index: compiler/AST/primitive.cpp
===================================================================
--- compiler/AST/primitive.cpp  (revision 23729)
+++ compiler/AST/primitive.cpp  (working copy)
@@ -418,6 +418,8 @@
   prim_def(PRIM_GET_REAL, "complex_get_real", returnInfoComplexField);
   prim_def(PRIM_GET_IMAG, "complex_get_imag", returnInfoComplexField);
   prim_def(PRIM_QUERY, "query", returnInfoUnknown);
+  prim_def(PRIM_QUERY_PARAM, "query param field", returnInfoGetMemberRef);
+  prim_def(PRIM_QUERY_TYPE, "query type field", returnInfoGetMember);
 
   prim_def(PRIM_ADDR_OF, "addr of", returnInfoRef);
   prim_def(PRIM_DEREF,   "deref",   returnInfoVal, false, true);
Index: compiler/include/primitive.h
===================================================================
--- compiler/include/primitive.h        (revision 23729)
+++ compiler/include/primitive.h        (working copy)
@@ -68,6 +68,8 @@
   PRIM_GET_REAL,            // get complex real component
   PRIM_GET_IMAG,            // get complex imag component
   PRIM_QUERY,               // query expression primitive
+  PRIM_QUERY_PARAM,
+  PRIM_QUERY_TYPE,
 
   PRIM_ADDR_OF,             // set a reference to a value
   PRIM_DEREF,               // dereference a reference
Index: compiler/main/checks.cpp
===================================================================
--- compiler/main/checks.cpp    (revision 23729)
+++ compiler/main/checks.cpp    (working copy)
@@ -440,6 +440,8 @@
         case PRIM_IS_SUBTYPE:
         case PRIM_TUPLE_EXPAND:
         case PRIM_QUERY:
+        case PRIM_QUERY_PARAM:
+        case PRIM_QUERY_TYPE:
         case PRIM_ERROR:
           if (call->parentSymbol)
             INT_FATAL("Primitive should no longer be in AST");
Index: compiler/optimizations/optimizeOnClauses.cpp
===================================================================
--- compiler/optimizations/optimizeOnClauses.cpp        (revision 23729)
+++ compiler/optimizations/optimizeOnClauses.cpp        (working copy)
@@ -223,6 +223,8 @@
   case PRIM_TUPLE_EXPAND:
   case PRIM_TUPLE_AND_EXPAND:
   case PRIM_QUERY:
+  case PRIM_QUERY_PARAM:
+  case PRIM_QUERY_TYPE:
   case PRIM_ERROR:
   case PRIM_WARNING:
 
Index: compiler/resolution/functionResolution.cpp
===================================================================
--- compiler/resolution/functionResolution.cpp  (revision 23729)
+++ compiler/resolution/functionResolution.cpp  (working copy)
@@ -5131,6 +5131,30 @@
           expr->replace(result);
         }
       }
+    } else if (call->isPrimitive(PRIM_QUERY_TYPE) ||
+               call->isPrimitive(PRIM_QUERY_PARAM)) {
+      SymExpr* classWrap = toSymExpr(call->get(1));
+      // Really should be a symExpr
+      INT_ASSERT(classWrap);
+      AggregateType* ct = toAggregateType(classWrap->var->type);
+      if (!ct) {
+        USR_FATAL(call, "Attempted to obtain field of a type that was not a 
record or class");
+      }
+      const char* memberName = get_string(call->get(2));
+      Symbol* sym = ct->getField(memberName);
+      // Finds the field matching the specified name.
+      Vec<Symbol *> keys;
+      ct->substitutions.get_keys(keys);
+      forv_Vec(Symbol, key, keys) {
+        if (!strcmp(sym->name, key->name)) {
+          // If there is a substitution for it, replace this call with that
+          // substitution
+          if (Symbol* value = ct->substitutions.get(key)) {
+              result = new SymExpr(value);
+              expr->replace(result);
+          }
+        }
+      }
     }
     // param initialization should not involve PRIM_ASSIGN or "=".
     else if (call->isPrimitive(PRIM_MOVE)) {
Index: test/classes/lydia/prettierQueryField.chpl
===================================================================
--- test/classes/lydia/prettierQueryField.chpl  (revision 0)
+++ test/classes/lydia/prettierQueryField.chpl  (working copy)
@@ -0,0 +1,8 @@
+record R {
+  param foo: int(64);
+
+}
+
+type t = R(5);
+var paramField = t.foo;
+writeln(paramField);
Index: test/classes/lydia/prettierQueryField.future
===================================================================
--- test/classes/lydia/prettierQueryField.future        (revision 0)
+++ test/classes/lydia/prettierQueryField.future        (working copy)
@@ -0,0 +1,9 @@
+feature request: Syntactic sugar for PRIM_QUERY_TYPE and PRIM_QUERY_PARAM
+
+It would be nice to be able to specify
+
+<type>.<fieldname>
+
+instead of having to type
+
+__primitive("query [type|param] field", <type>, "<fieldname>")
Index: test/classes/lydia/prettierQueryField.good
===================================================================
--- test/classes/lydia/prettierQueryField.good  (revision 0)
+++ test/classes/lydia/prettierQueryField.good  (working copy)
@@ -0,0 +1 @@
+5
Index: test/classes/lydia/queryNonAggregateType.chpl
===================================================================
--- test/classes/lydia/queryNonAggregateType.chpl       (revision 0)
+++ test/classes/lydia/queryNonAggregateType.chpl       (working copy)
@@ -0,0 +1,3 @@
+type t = bool;
+var foo = __primitive("query param field", t, "foo");
+writeln(foo);
\ No newline at end of file
Index: test/classes/lydia/queryNonAggregateType.good
===================================================================
--- test/classes/lydia/queryNonAggregateType.good       (revision 0)
+++ test/classes/lydia/queryNonAggregateType.good       (working copy)
@@ -0,0 +1 @@
+queryNonAggregateType.chpl:2: error: Attempted to obtain field of a type that 
was not a record or class
Index: test/classes/lydia/queryParamFields.chpl
===================================================================
--- test/classes/lydia/queryParamFields.chpl    (revision 0)
+++ test/classes/lydia/queryParamFields.chpl    (working copy)
@@ -0,0 +1,8 @@
+record R {
+  param foo: int(64);
+
+}
+
+type t = R(5);
+var paramField = __primitive("query param field", t, "foo");
+writeln(paramField);
Index: test/classes/lydia/queryParamFields.good
===================================================================
--- test/classes/lydia/queryParamFields.good    (revision 0)
+++ test/classes/lydia/queryParamFields.good    (working copy)
@@ -0,0 +1 @@
+5
Index: test/classes/lydia/queryParamFieldsClass.chpl
===================================================================
--- test/classes/lydia/queryParamFieldsClass.chpl       (revision 0)
+++ test/classes/lydia/queryParamFieldsClass.chpl       (working copy)
@@ -0,0 +1,8 @@
+record R {
+  param foo: int(64);
+
+}
+
+type t = R(5);
+var paramField = __primitive("query param field", t, "foo");
+writeln(paramField);
Index: test/classes/lydia/queryParamFieldsClass.good
===================================================================
--- test/classes/lydia/queryParamFieldsClass.good       (revision 0)
+++ test/classes/lydia/queryParamFieldsClass.good       (working copy)
@@ -0,0 +1 @@
+5
Index: test/classes/lydia/queryTypeFields.chpl
===================================================================
--- test/classes/lydia/queryTypeFields.chpl     (revision 0)
+++ test/classes/lydia/queryTypeFields.chpl     (working copy)
@@ -0,0 +1,8 @@
+record R {
+  type foo;
+
+}
+
+type t = R(bool);
+type typeField = __primitive("query type field", t, "foo");
+writeln(typeToString(typeField));
Index: test/classes/lydia/queryTypeFields.good
===================================================================
--- test/classes/lydia/queryTypeFields.good     (revision 0)
+++ test/classes/lydia/queryTypeFields.good     (working copy)
@@ -0,0 +1 @@
+bool
Add ability to access an AggregateType's param and type fields [reviewed by ]

This patch adds the primitives PRIM_QUERY_TYPE and PRIM_QUERY_PARAM to the
compiler, enabling access to a given record or class type's param or type fields
from Chapel code.  For some class C defined as:

class C {
  param foo: <anytype>;
}

or 

class C {
  type foo;
}

the user can grab and re-use the contents of the field foo without calling a
getter on a specific instantiation of the class.  This is done by calling:

__primitive("query param field", t, "foo");

or

__primitive("query type field", t, "foo");

respectively, where t in this case is a generic instantiation of class C such
that the field foo has a value associated with it.

Summary of changes:
compiler/AST/primitive.cpp
compiler/include/primitive.h
compiler/main/checks.cpp
compiler/optimizations/optimizeOnClauses.cpp
  Add checks and basic presence of PRIM_QUERY_TYPE and PRIM_QUERY_PARAM

compiler/resolution/functionResolution.cpp
  Implementation of the primitives.  During function resolution, replace calls
  to these primitives with the substitution provided by the type instantiation
  if one exists.

test/classes/lydia/*.chpl
  Some tests of the functionality of these primitives.  Ensures they work in the
  basic case, a common source of error (called on non-AggregateType), and a
  future describing our ideal syntactic sugar for this functionality.

  Note the absence of a test where the user specifies a field that does not
  exist.  When looking through the compiler, I noticed a TODO in the getFields
  method to generate a user error in some cases rather than always an internal
  error.  Since this is the same situation, I figured a future was already in
  place and so have forgone a specialized error message for the time being.

tested over std/
------------------------------------------------------------------------------
Open source business process management suite built on Java and Eclipse
Turn processes into business applications with Bonita BPM Community Edition
Quickly connect people, data, and systems into organized workflows
Winner of BOSSIE, CODIE, OW2 and Gartner awards
http://p.sf.net/sfu/Bonitasoft
_______________________________________________
Chapel-developers mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/chapel-developers

Reply via email to