Newbie questions about Pliant

Newbie questions about Pliant

Dividing a generic number

I'd like to define a generic scalar, that can be either a
Float, or an Int of some size, or anything else that
appears appropriate.

Later, I'd like to define vectors and matrices of this
scalar type.

I'm having troubles with this early on...
Message posted by Micky Latowicki on 2001/10/12 10:58:26
I took the sample code from generic functions doc and changed it a little:

module "/pliant/language/compiler.pli"

type Number
  void
Number maybe Int
Number maybe Intn
Number maybe Float

method n '*' d -> r
  arg Number n d r
  generic
  r := n  # just so that r is defined and we can see if its value is incorrect

gvar Link:Int i :> new Int
i := 5
gvar Link:Number n :> i
n := n * 2
console n eol

The compiler output seems to indicate a compiler bug, if I understand correctly:

exception
----------------------------------------------------------------
processor stack content is:
destroy (Instruction) +79
destroy (Instruction) +3072
optimize_rewrite_instructions +617
. optimize (GeneratorContext) +457
external +2511
method +16
active_type_Meta +101
. compile_step4 (Expression Address Int) +274
active_type_Ident +215
. compile_step4 (Expression Address Int) +274
. compile_step3 (Expression) +18
. compile_step2 (Expression) +64
. compile (Expression) +17
  file:Number.pli (internals) 9 1
{} +44
active_type_Meta +101
. compile_step4 (Expression Address Int) +274
active_type_Ident +215
. compile_step4 (Expression Address Int) +274
. compile_step3 (Expression) +18
. compile_step2 (Expression) +64
. compile (Expression) +17
  file:Number.pli (internals) 9 1
. execute (Expression) +21
  file:Number.pli (internals) 9 1
. execute (ParserContext) +39
parser_filter_execute +322
pliant internal parse_one_token function (ParserContext) +468
compile_text (List Module) +259
pliant_load_module (Str Module Int Module) +952
pliant internal startup function +2549
???
???

Any pointers would be appreciated, thanks.
Message posted by maybe Hubert Tonneau on 2001/10/12 12:06:32
You are misunderstanding what Pliant generic methods are:
. they are a way to provide several definitions for a 'same' function,
  with the runtime engine selecting the right one, using the real
  type of the object to decide.
. they are not a kind of templates.

Your exemple is incorrect because:
. Since 'Number' has no field, it is equivalent to 'Void' so assigning is
  just like doing nothing.
. '*' is not a method, so 'n * 2' will never call what you have just defined.
Message posted by maybe Patrice Ossona de Mendez on 2001/10/12 14:34:06
May be done, but quite tricky as a Link:Number has to be returned and type
handled "by hand" at runtime:

module "/pliant/language/compiler.pli"

type Number
   void
Number maybe Int
Number maybe uInt # constant 2 is uInt, should be a Number
Number maybe Intn
Number maybe Float

#
# 'to string' method for Numbers (used by console).
#
# Principe: get the true type of the data, search the generic method to convert into a string
# and call it.
#
constant to_index (the_function '. to string' Universal Str -> Str):generic_index 

function to_string data options function -> string
  arg Universal data ; arg Str options ; arg Function function ; arg Str string
  indirect 

method n 'to string' options -> string
 oarg Number n; arg Str options string
 var Pointer:Function function :> entry_type:(addressof n) get_generic_method to_index
 if addressof:function=null or addressof:function=addressof:(the_function '. to string' Universal Str -> Str)
   string :="??"
 string:= to_string n options function
   
#
# '*' function on Numbers
#
meta '*' e
  if e:size<>2 or not (e:0 cast Number) or not (e:1 cast Number)
     # both arguments should be Number
     return

  # compile e:0 and keep instruction list
  # one should add 'e suckup e:1' if second argument where used...
  e suckup e:0

  # objad will get the address of first argument

  var Link:Argument objad :> argument local Address
  e add (instruction (the_function 'address Universal' Universal -> Address) e:0:result objad)

  # true_type should be set to the type of the first argument

  var Link:Argument add :> argument local Address
  var Link:Argument true_type :> argument indirect Type add 0
  e add (instruction (the_function entry_type Address -> Type) objad true_type)

  # create a new Number object (object) with type 'true_type' and a link to it (link) as Link:Number.

  var Link:Argument link :> argument local Link:Number
  var Link:Argument object :> argument indirect Number link 0
  e add (instruction (the_function entry_new Type -> Address) true_type link) 
  e add (instruction (the_function entry_lock Address) link)

  # copy the result of the first argument to the newly created object. As the type is not known
  # at compile time, the method copy_instance should be called instead of
  # 'copy Universal' function.

  e add (instruction (the_function '. copy_instance' Type Address Address) true_type objad link)   

  # set the result

  e set_result object access_read+access_object


gvar Link:Int i :> new Int
i := 5
gvar Link:Number n :> i
n :> n * 2  # n will link to the result.
i := 7 # change i to check n does not link to it any more
console n eol # should display "5".

Message posted by maybe Patrice Ossona de Mendez on 2001/10/12 14:38:09
By the way, this is probably not what you really need.
Will you work with matrices with mixed element types ?
If all element will get the same type, you would probably
need a kind of template, like Array.
Message posted by Micky Latowicki on 2001/10/17 06:42:29
Thanks for your detailed replies. Patrice's is a bit over my head at 
the moment, as I lack too much knowledge about writing metas, and 
about the compiler's internal workings.

I understand now that what I need is more along the lines of 
a template. I intend to study the array code a little 
before proceeding with this.

Thanks.