PRT.PRDSLDevelop History

Hide minor edits - Show changes to markup - Cancel

August 02, 2013, at 10:59 PM by 82.139.115.35 -
Changed line 18 from:

This page discusses what drove me to call such things programming languages. In short, I've taken to thinking of a programming language as the embodiment of the semantics, with a syntax and grammar front-end interface. Looked at that way, it's natural to think of a function call API a perfectly valid interface, acting as the equivalent of a more traditional syntax, while the grammar is the valid combinations of calls that a user is responsible for respecting. Hence, even though PR_DSL behavior is only invoked via calls to its wrapper-library, I think of it as a programming language. The discussion page points out the subtleties and gray areas around choices of definition of "programming language".

to:

This page discusses what drove me to call such things programming languages. In short, I've taken to thinking of a programming language as the embodiment of the semantics, with a syntax and grammar front-end interface. Looked at that way, it's natural to think of a function call API as a perfectly valid interface, acting as the equivalent of a more traditional syntax, while the grammar is the valid combinations of calls that a user is responsible for respecting. Hence, even though PR_DSL behavior is only invoked via calls to its wrapper-library, I think of it as a programming language. The discussion page points out the subtleties and gray areas around choices of definition of "programming language".

August 02, 2013, at 09:31 PM by 82.139.115.35 -
Changed lines 16-18 from:

As a side-note, within proto-runtime work, it is common to call the runtime system plus wrapper library as a "programming language" or "proto-language". This brings up the question: what is the definition of "programming language"?

This page discusses what drove me to this way of thinking. In short, I've taken to thinking of a programming language as the embodiment of the semantics, with a syntax and grammar front-end interface. Looked at that way, it's natural to think of a function call API a perfectly valid interface, acting as the equivalent of a more traditional syntax, while the grammar is the valid combinations of calls that a user is responsible for respecting. Hence, even though PR_DSL behavior is only invoked via calls to its wrapper-library, I think of it as a programming language. The discussion page points out the subtleties and gray areas around choices of definition of "programming language".

to:

As a side-note, within proto-runtime work, it is common to call a particular runtime system plus its wrapper library as a "programming language" or "proto-language". This brings up the question: what is the definition of "programming language"?

This page discusses what drove me to call such things programming languages. In short, I've taken to thinking of a programming language as the embodiment of the semantics, with a syntax and grammar front-end interface. Looked at that way, it's natural to think of a function call API a perfectly valid interface, acting as the equivalent of a more traditional syntax, while the grammar is the valid combinations of calls that a user is responsible for respecting. Hence, even though PR_DSL behavior is only invoked via calls to its wrapper-library, I think of it as a programming language. The discussion page points out the subtleties and gray areas around choices of definition of "programming language".

August 02, 2013, at 09:29 PM by 82.139.115.35 -
Changed lines 21-38 from:

Baby step: Hello world language on top of proto-runtime

I would like to try to get something simple running in VMS so that I can better understand its goals and how it works.

it occurs to me that we sort of have a chicken versus egg thing here.. let me explain why..

So, proto-runtime is something that is "incomplete" in the sense that it is incapable of doing anything without behavior being plugged in.. what proto-runtime provides is the time-related aspects around that behavior.

Now, from past experience, I realise that the concepts take some getting used to.. so, my proposal is to pick a set of "behaviors", and then I'll implement those, as a plugin to proto-runtime. We'll call that PR_DSL.

So, here's a link to some wiki pages that explain how to download a proto-runtime project and get it working.. however, based on past experiences, I suspect too much of it will be "mystical" and confusing, and so counter-productive. But, here it is: http://opensourceresearchinstitute.org/pmwiki.php/VMS/DevelopProjectSSRMatrixMult

So, just to clarify, this was version 1.0 of proto-runtime, and was called "VMS".. it is primitive compared to where things are now.. but that makes it a good start for learning.. the application is blocked matrix multiply, and the language is "SSR", which is Synchronous Send-Receive.. a toy language I created in order to illustrate using proto-runtime..

Sample Code

to:

More about proto-runtime, and why make a PR_DSL

From past experience, I realise that the concepts involved with proto-runtime take some getting used to. For example, proto-runtime is something that is "incomplete" in the sense that it is incapable of doing anything without behavior being plugged in. What proto-runtime provides is the time-related aspects around that behavior.

So, to shield DSL implementors from having to learn those concepts, we provide PR_DSL, as a full proto-language. That way, DSL implementors just target PR_DSL constructs, and don't have to worry about implementing their own proto-runtime plugins. For some DSLs, their execution model will be such that they don't map onto PR_DSL so well.. for them, PR_DSL might still serve as a first baby step, and then custom proto-runtime constructs will be created that directly implement the execution model of the DSL.

For those who _really_ want to learn about proto-runtime, here's a link to some wiki pages that explain how to download a proto-runtime project and get it working.. however, based on past experiences, I suspect too much of it will be "mystical" and confusing, and so counter-productive. But, here it is: http://opensourceresearchinstitute.org/pmwiki.php/VMS/DevelopProjectSSRMatrixMult (just to clarify, this project uses version 1.0 of proto-runtime, which was called "VMS".. it is primitive compared to where things are now.. but that makes it a good start for learning.. the application in the project is blocked matrix multiply, and the language is "SSR", which is Synchronous Send-Receive.. a toy language I created in order to illustrate using proto-runtime..)

"Hello World" Sample Code

Now, here is some code written in a simple custom language, followed by what the language tool will translate that code into.

Changed lines 36-54 from:

Where "PR_DSL" is a special language I will create, for you to use as part of implementing DSLs.

To be honest, I have spent far more time improving the proto-runtime "features" than on creating easy-to-understand tutorials.. so, the pointer above to the matrix-multiply example is the only one that really works.. but it's not as simple as a "hello world" should be.. I really need to create some code that is used just for learning about proto-runtime..

Quick answers: On PR_DSL__start() -- PR_DSL__start() is a construct of the intermediate language, which I write and supply to you. A language has to be started before constructs from it can be used.

On Process vs Task: a process is equivalent to a Linux process -- it run a whole-program, where the program uses multiple languages and creates multiple pieces of work. In contrast, a task is one piece of work, created by a language, within application code. Of course, a task can create other tasks.. but those other tasks exist inside the process, not inside the task that caused their creation.. experience with implementation will clear this up..

Put another way, it goes as follows: -] before the parallel application code can run, a process is created, which is what runs the application. -] Inside that process, proto-runtime languages can be started, and then constructs from those languages can be used -] after a proto-runtime language has been started, inside a process, then constructs from that language can be used to create tasks. -] each task is one atomic piece of work that has constraints on when it can run, relative to other tasks. When it is free to run, then an assigner places it onto a particular core. The work of the task happens there.

If you would like a deeper understanding, then it's probably best to spend some time implementing runtime systems and/or operating systems.. direct experience is the only way I know of to gain the patterns needed.. it's implementation related stuff. I can point you to places in the code to look, if you want to dive into those details..

to:
Added lines 95-108:

some notes on the code -----------

On PR_DSL__start() -- The proto-runtime requires each proto-language to supply a function that creates language-internal data structures and initializes them. This must be invoked before any constructs from that language can be used.

On Process vs Task: a proto-runtime process is equivalent to a Linux process -- it runs a whole-program, where the program uses multiple languages and creates multiple pieces of work. In contrast, a task is one piece of work, created by a language, within application code. Of course, a task can create other tasks.. but those other tasks exist inside the process, not inside the task that caused their creation.. the need for this distinction is largely inside fundamental implementation patterns..

Put another way, the process of running application code goes as follows: -] before the parallel application code can run, a process is created, which is what then runs the application. -] Inside that process, proto-runtime languages can be started, after which constructs from those languages can be used -] after a proto-runtime language has been started, inside a process, then constructs from that language can be used to create tasks (or virtual processors, equiv to threads). -] each task is one atomic piece of work that has constraints on when it can run, relative to other tasks. When it is free to run, then an assigner places it onto a particular core. The work of the task happens on that core.

A deeper understanding will come from time spent implementing runtime systems and/or operating systems.. direct experience appears to be the only way to acquire the mental patterns needed to understand.

August 02, 2013, at 09:06 PM by 82.139.115.35 -
Added line 12:
  • PR_DSL__wait_for_target_task_to_complete
August 02, 2013, at 09:06 PM by 82.139.115.35 -
Changed lines 5-17 from:

One thing that happens in DSL design is determining what the types and values are that will be manipulated by the language and what the operations will be on those values. As a language implementer it is my job to figure out what these operations translate to in some target language.

Right. That target language is the combination of C + PR_DSL, perhaps with PR_DKU as an additional target to provide dynamic task-sizing..

PR_DSL just has a small number of constructs (calls).. all the DSL constructs will be translated into C, and in addition, the DSL construct that have parallelism behavior will be translated into C plus some combination of PR_DSL calls, which create tasks and establish dependencies among them.

As a side-note, within proto-runtime work, it is common to call the runtime system plus wrapper library as a "programming language". This brings up the question: what is the definition of "programming language"?

I've taken to thinking of a programming language as the embodiment of the semantics, and treating the function call API used to invoke that behavior as a perfectly valid syntax, while the grammar is implied by the combinations of calls that a user is supposed to make. Hence, even though PR_DSL behavior is only invoked via calls to its wrapper-library, I think of it as a programming language.

A fuller discussion of what drove me to choose this way of looking at things is given here

to:

One thing that happens in DSL design is determining what the types and values are that will be manipulated by the language and what the operations will be on those values. As a language implementer it is my job to figure out what these operations translate to in some target language. In the case of PR_DSL, that target language is the combination of C + PR_DSL, perhaps with PR_DKU as an additional target to provide dynamic task-sizing..

PR_DSL just has a small number of constructs (calls), which we are figuring out in the course of this collaboration. The starting list is:

  • PR_DSL__create_task
  • PR_DSL__attach_propendent_to_task
  • PR_DSL__attach_dependent_to_task
  • PR_DSL__wait_for_descendent_tasks_to_complete

All the DSL constructs will be translated either into straight C, or into C plus some combination of PR_DSL calls.

As a side-note, within proto-runtime work, it is common to call the runtime system plus wrapper library as a "programming language" or "proto-language". This brings up the question: what is the definition of "programming language"?

This page discusses what drove me to this way of thinking. In short, I've taken to thinking of a programming language as the embodiment of the semantics, with a syntax and grammar front-end interface. Looked at that way, it's natural to think of a function call API a perfectly valid interface, acting as the equivalent of a more traditional syntax, while the grammar is the valid combinations of calls that a user is responsible for respecting. Hence, even though PR_DSL behavior is only invoked via calls to its wrapper-library, I think of it as a programming language. The discussion page points out the subtleties and gray areas around choices of definition of "programming language".

Deleted line 116:
August 02, 2013, at 08:27 PM by 82.139.115.35 -
Deleted lines 16-29:

This does, indeed, differ from how many in the field think of "language". I evolved into this way of thinking while working with implementing programming languages and coming to regard the behavior as the essential aspect. It turns out that many different syntaxes and grammars can be used as front ends to the same behavior.. which makes the particular choice of syntax and grammar feel like the interface, while the behavior is the essence.

For example, consider gibberish.. is it a language? Even if it has well defined syntax and grammar, there is no meaning attached, no behavior. Some would argue "the lack of meaning just makes it a useless language, it doesn't have to be useful to anyone in order to be a language". But I feel that a definition should capture all the essential elements. True, defining language as just syntax and grammar is a valid choice, but I prefer the addition of the third element, semantics, before I consider it a _programming_ language. Also, I consider syntax and grammar in the form of an API as perfectly valid. Others argue that it's only a syntax and grammar if you have a lexical analyzer, or can state it in BNF notation, etc. That's also a perfectly valid choice, but I prefer a broader definition that doesn't focus on particular details of the form of the syntax and grammar.

To me, the behaviors are the essence, no matter what interface is used. For example, each function call of PR_DSL can be given a traditional syntactic and grammatic form. Is it now a language where it wasn't before? It's the same thing, just a different way of invoking the behavior. In fact, for the "PR_DSL__create_task( &birthFn, data)" call, I could just define the syntax to be "PR_DSL__create_task birthFn data" -- and define the grammar for the placement of the two arguments. Now is it a language? But it wasn't before?

So, in the end, there's gray area, leaving people free to pick where in that gray region they want to draw the line..

Which brings up the question of what we call these things while talking with each other.. are you up for indulging me.. let me call them "languages" or "langlets"? proto-language would be fine, too, especially if you feel uncomfortable with treating function calls as syntax.. then, a programming language would be a particular kind of syntax and grammar, plus the behaviors represented by them, and a proto-language implements the behaviors indicated by the syntax and grammar. But an interface to a proto-language can be supplied that allows directly invoking the behavior without using a special syntax and grammar.

But, as I read that, it feels weak, making the distinction be only the form of the syntax and grammar. A language has some chosen type of form as the interface, while a function call is not an acceptable form of interface. The main difference is that type checking and grammar checking can only be done dynamically when using the function call interface.

But, I can get over it, and go with proto-language

August 02, 2013, at 08:26 PM by 82.139.115.35 -
Changed lines 12-14 from:

As a side-note, within proto-runtime work, it is common to call the runtime system plus wrapper library as a "language". This brings up the question: what is the definition of "language"?

I've taken to thinking of a programming language as the embodiment of the semantics, and treating the function call API used to invoke that behavior as a perfectly valid syntax, while the grammar is implied by the combinations of calls that a user is supposed to make. Hence, even though PR_DSL behavior is only invoked via calls to its wrapper-library, I think of it as a language.

to:

As a side-note, within proto-runtime work, it is common to call the runtime system plus wrapper library as a "programming language". This brings up the question: what is the definition of "programming language"?

I've taken to thinking of a programming language as the embodiment of the semantics, and treating the function call API used to invoke that behavior as a perfectly valid syntax, while the grammar is implied by the combinations of calls that a user is supposed to make. Hence, even though PR_DSL behavior is only invoked via calls to its wrapper-library, I think of it as a programming language.

A fuller discussion of what drove me to choose this way of looking at things is given here

August 02, 2013, at 04:12 PM by 82.139.115.35 -
Added lines 68-78:
   ------- Original Source, using custom DSL syntax -------
   int size = 1000;
   int data[];
   data = makeArray( size );

   IterateIndependently i in 1:size
    { data[i] = square( i );
    }

   -------  What it translates into -------
August 02, 2013, at 04:10 PM by 82.139.115.35 -
Changed lines 70-72 from:
   int main() {
     PRProcess *myProcess;
     SeedParams *paramsForSeed = malloc( sizeof(SeedParasm) );  //only carries data as return result
to:
   int main() 
    {
      PRProcess *myProcess;
      SeedParams *paramsForSeed = malloc( sizeof(SeedParasm) );  //only carries data as return result
Changed lines 75-76 from:
     PR__Start();
     myProcess = PR__create_process( &my_seed_birth_Fn, paramsForSeed );
to:
      PR__Start();
      myProcess = PR__create_process( &my_seed_birth_Fn, paramsForSeed );
Changed lines 78-79 from:
     PR__wait_for_process_to_end( myProcess );
     do_something_with_results( paramsForSeed->data );
to:
      PR__wait_for_process_to_end( myProcess );
      do_something_with_results( paramsForSeed->data );
Changed line 81 from:
     PR__Shutdown();
to:
      PR__Shutdown();
Changed lines 84-115 from:

void my_seed_birth_Fn( void *_params, SlaveVP *animatingVP) {

  int size = 1000 ;
  int *data = (int *) PR__malloc (size * sizeof(int)) ;
  SeedParams *seedParams = (SeedParams *)_params; //used to comm with main()

  PR_DSL__start(); //starts the PR_DSL langlet -- does internal stuff inside proto-runtime..
  //can start additional languages here, and then freely mix "constructs" from them  

  int i ;
  int chunkSize = 100; //for portability, lang would choose this dynamically at run time
  for (i=0; i < size; ++chunkSize) {
    params = PR__malloc(sizeof(TaskParams)); //these define work the task performs
    params->start = i;
    params->end = i + chunkSize -1;
    PR_DSL__create_task( params, &task_birthFn, animatingVP );
  }
 PR_DSL__wait_for_tasks_to_complete();
 seedParams->data = data; //sends results back to main()
 PR_DSL__end_seedVP();

}

int square (int x) { return x*x; }

void task_birth_Fn( void *_params){ //all birth functions have the same, fixed, prototype

  TaskParams *params = (TaskParams *)_params;
  for (i=params->start; i < params->end; ++i) {
    data[i] = square(i) ;
  PR_DSL__taskEnd;  

}

I'm also not clear on the distinction between 'process' and 'task'.

to:
   void my_seed_birth_Fn( void *_params, SlaveVP *animatingVP) 
    {
      int size = 1000 ;
      int *data = (int *) PR__malloc (size * sizeof(int)) ;
      SeedParams *seedParams = (SeedParams *)_params; //used to comm with main()

      PR_DSL__start(); //starts the PR_DSL langlet -- does internal stuff inside proto-runtime..
      //can start additional languages here, and then freely mix "constructs" from them  

      int i ;
      int chunkSize = 100; //for portability, lang would choose this dynamically at run time
      for (i=0; i < size; ++chunkSize) 
       { params = PR__malloc(sizeof(TaskParams)); //these define work the task performs
         params->start = i;
         params->end = i + chunkSize -1;
         PR_DSL__create_task( params, &task_birthFn, animatingVP );
       }
      PR_DSL__wait_for_tasks_to_complete();
      seedParams->data = data; //sends results back to main()
      PR_DSL__end_seedVP();
    }

   int square (int x) { return x*x; }

   void task_birth_Fn( void *_params)   //all birth functions have the same, fixed, prototype
    {
      TaskParams *params = (TaskParams *)_params;
      for (i=params->start; i < params->end; ++i) 
       { data[i] = square(i) ;
         PR_DSL__taskEnd;  
       }
    }
August 02, 2013, at 04:06 PM by 82.139.115.35 -
Added lines 1-114:

Context for PR_DSL

How does PR_DSL fit into DSL implementation?

One thing that happens in DSL design is determining what the types and values are that will be manipulated by the language and what the operations will be on those values. As a language implementer it is my job to figure out what these operations translate to in some target language.

Right. That target language is the combination of C + PR_DSL, perhaps with PR_DKU as an additional target to provide dynamic task-sizing..

PR_DSL just has a small number of constructs (calls).. all the DSL constructs will be translated into C, and in addition, the DSL construct that have parallelism behavior will be translated into C plus some combination of PR_DSL calls, which create tasks and establish dependencies among them.

As a side-note, within proto-runtime work, it is common to call the runtime system plus wrapper library as a "language". This brings up the question: what is the definition of "language"?

I've taken to thinking of a programming language as the embodiment of the semantics, and treating the function call API used to invoke that behavior as a perfectly valid syntax, while the grammar is implied by the combinations of calls that a user is supposed to make. Hence, even though PR_DSL behavior is only invoked via calls to its wrapper-library, I think of it as a language.

This does, indeed, differ from how many in the field think of "language". I evolved into this way of thinking while working with implementing programming languages and coming to regard the behavior as the essential aspect. It turns out that many different syntaxes and grammars can be used as front ends to the same behavior.. which makes the particular choice of syntax and grammar feel like the interface, while the behavior is the essence.

For example, consider gibberish.. is it a language? Even if it has well defined syntax and grammar, there is no meaning attached, no behavior. Some would argue "the lack of meaning just makes it a useless language, it doesn't have to be useful to anyone in order to be a language". But I feel that a definition should capture all the essential elements. True, defining language as just syntax and grammar is a valid choice, but I prefer the addition of the third element, semantics, before I consider it a _programming_ language. Also, I consider syntax and grammar in the form of an API as perfectly valid. Others argue that it's only a syntax and grammar if you have a lexical analyzer, or can state it in BNF notation, etc. That's also a perfectly valid choice, but I prefer a broader definition that doesn't focus on particular details of the form of the syntax and grammar.

To me, the behaviors are the essence, no matter what interface is used. For example, each function call of PR_DSL can be given a traditional syntactic and grammatic form. Is it now a language where it wasn't before? It's the same thing, just a different way of invoking the behavior. In fact, for the "PR_DSL__create_task( &birthFn, data)" call, I could just define the syntax to be "PR_DSL__create_task birthFn data" -- and define the grammar for the placement of the two arguments. Now is it a language? But it wasn't before?

So, in the end, there's gray area, leaving people free to pick where in that gray region they want to draw the line..

Which brings up the question of what we call these things while talking with each other.. are you up for indulging me.. let me call them "languages" or "langlets"? proto-language would be fine, too, especially if you feel uncomfortable with treating function calls as syntax.. then, a programming language would be a particular kind of syntax and grammar, plus the behaviors represented by them, and a proto-language implements the behaviors indicated by the syntax and grammar. But an interface to a proto-language can be supplied that allows directly invoking the behavior without using a special syntax and grammar.

But, as I read that, it feels weak, making the distinction be only the form of the syntax and grammar. A language has some chosen type of form as the interface, while a function call is not an acceptable form of interface. The main difference is that type checking and grammar checking can only be done dynamically when using the function call interface.

But, I can get over it, and go with proto-language

Baby step: Hello world language on top of proto-runtime

I would like to try to get something simple running in VMS so that I can better understand its goals and how it works.

it occurs to me that we sort of have a chicken versus egg thing here.. let me explain why..

So, proto-runtime is something that is "incomplete" in the sense that it is incapable of doing anything without behavior being plugged in.. what proto-runtime provides is the time-related aspects around that behavior.

Now, from past experience, I realise that the concepts take some getting used to.. so, my proposal is to pick a set of "behaviors", and then I'll implement those, as a plugin to proto-runtime. We'll call that PR_DSL.

So, here's a link to some wiki pages that explain how to download a proto-runtime project and get it working.. however, based on past experiences, I suspect too much of it will be "mystical" and confusing, and so counter-productive. But, here it is: http://opensourceresearchinstitute.org/pmwiki.php/VMS/DevelopProjectSSRMatrixMult

So, just to clarify, this was version 1.0 of proto-runtime, and was called "VMS".. it is primitive compared to where things are now.. but that makes it a good start for learning.. the application is blocked matrix multiply, and the language is "SSR", which is Synchronous Send-Receive.. a toy language I created in order to illustrate using proto-runtime..

Sample Code

PR_DSL__create_task( &taskBirthFn, ptrToTaskParams);

Where "PR_DSL" is a special language I will create, for you to use as part of implementing DSLs.

To be honest, I have spent far more time improving the proto-runtime "features" than on creating easy-to-understand tutorials.. so, the pointer above to the matrix-multiply example is the only one that really works.. but it's not as simple as a "hello world" should be.. I really need to create some code that is used just for learning about proto-runtime..

Quick answers: On PR_DSL__start() -- PR_DSL__start() is a construct of the intermediate language, which I write and supply to you. A language has to be started before constructs from it can be used.

On Process vs Task: a process is equivalent to a Linux process -- it run a whole-program, where the program uses multiple languages and creates multiple pieces of work. In contrast, a task is one piece of work, created by a language, within application code. Of course, a task can create other tasks.. but those other tasks exist inside the process, not inside the task that caused their creation.. experience with implementation will clear this up..

Put another way, it goes as follows: -] before the parallel application code can run, a process is created, which is what runs the application. -] Inside that process, proto-runtime languages can be started, and then constructs from those languages can be used -] after a proto-runtime language has been started, inside a process, then constructs from that language can be used to create tasks. -] each task is one atomic piece of work that has constraints on when it can run, relative to other tasks. When it is free to run, then an assigner places it onto a particular core. The work of the task happens there.

If you would like a deeper understanding, then it's probably best to spend some time implementing runtime systems and/or operating systems.. direct experience is the only way I know of to gain the patterns needed.. it's implementation related stuff. I can point you to places in the code to look, if you want to dive into those details..

   //the main fn just acts as a "shell" that starts up proto-runtime and creates a process within it
   int main() {
     PRProcess *myProcess;
     SeedParams *paramsForSeed = malloc( sizeof(SeedParasm) );  //only carries data as return result

     PR__Start();
     myProcess = PR__create_process( &my_seed_birth_Fn, paramsForSeed );

     PR__wait_for_process_to_end( myProcess );
     do_something_with_results( paramsForSeed->data );

     PR__Shutdown();
    }

void my_seed_birth_Fn( void *_params, SlaveVP *animatingVP) {

  int size = 1000 ;
  int *data = (int *) PR__malloc (size * sizeof(int)) ;
  SeedParams *seedParams = (SeedParams *)_params; //used to comm with main()

  PR_DSL__start(); //starts the PR_DSL langlet -- does internal stuff inside proto-runtime..
  //can start additional languages here, and then freely mix "constructs" from them  

  int i ;
  int chunkSize = 100; //for portability, lang would choose this dynamically at run time
  for (i=0; i < size; ++chunkSize) {
    params = PR__malloc(sizeof(TaskParams)); //these define work the task performs
    params->start = i;
    params->end = i + chunkSize -1;
    PR_DSL__create_task( params, &task_birthFn, animatingVP );
  }
 PR_DSL__wait_for_tasks_to_complete();
 seedParams->data = data; //sends results back to main()
 PR_DSL__end_seedVP();

}

int square (int x) { return x*x; }

void task_birth_Fn( void *_params){ //all birth functions have the same, fixed, prototype

  TaskParams *params = (TaskParams *)_params;
  for (i=params->start; i < params->end; ++i) {
    data[i] = square(i) ;
  PR_DSL__taskEnd;  

}

I'm also not clear on the distinction between 'process' and 'task'.