Primitive (future version)
From Dyna
Like most languages, Dyna has some built-in primitive types.
Most Dyna users only need string, int, and double, so you can skip most of this page on a first reading.
This section is rather boring because Dyna essentially just borrows the primitive types of C++. If necessary, you can also import almost any C++ class as a new primitive type in Dyna.
Contents |
Strings
One primitive type is string.
A Dyna program may contain string literals, which are written exactly
as in C++ [1] or Perl:
"apples" "Äpfel" "This is a sentence.\n" "\"This is a sentence\" he said.\n"
- We don't currently handle wide strings like L"asdf", but perhaps we should.
Booleans (not implemented yet)
Like C++, Dyna has a primitive bool type. A Dyna
program may contain the literal constants true and
false.
Numeric types
Dyna has the basic C/C++ numeric types, such as int,
float, and double. Literals of these types
are written exactly as in C++ [2]
[3]:
3 3L 3.0 3.0L
- I think so far, the only numeric types that are implemented are int and double. When the rest go in, don't forget about char, and modifiers like short, long, unsigned. May get a little tricky.
- It is tempting to use the simpler and more portable Java type system instead. But that would result in mismatches in number of bits between a Dyna program and its C++ driver program.
The usual C++ rules [4] apply for numeric promotion and conversion. For example, an int or float may be used where a double is needed.
- We may be able to play some games with unions of numeric types, e.g., the union [int,double] might just be represented as double, by using promotion rather than boxing.
Imported primitive types
- This feature is not yet fully implemented ...
You can import your own C++ classes as new primitive types.
For example, suppose you have implemented a class called complex to represent complex numbers, and the header file <complex.h>. Include the following directives in your Dyna program:
:- c_include(complex, "<complex.h>"). :- primitive(complex).
The first line ensures that the C++ code that is generated by the Dyna compiler contains the line
#include <complex.h>
so that it will later be able to refer to the C++ complex class.
Requirements on imported primitive types
complex must be a C++ class ...
It must support at least the following methods ...
To use it as the value of an expression, it must also support the following methods ...
To build bigger expressions by applying functions like + and exp to complex numbers, ...
Discuss destructors ... copying, heap ...hashing ... relation to storage disciplines like interning ... whether you will pass in a value or a reference ...
Obtaining values of imported types
If you create a C++ class complex, there is no way to
get C++ to parse something like 3+4i as a complex literal.
You can't get Dyna to do that either:
:- structure(conjugate(complex z)). :- item(conjugate, complex, 0). conjugate(3+4i) = 3-4i. % no way to do this
Rather, a C++ user would create 3+4i by calling a constructor of the complex class. Dyna can call those C++ constructors too:
:- structure(conjugate(complex z)).
:- item(conjugate, complex, complex(0,0)). % uses constructor complex(double,double)
conjugate(=complex(3,4)) = complex(3,-4). % uses constructor complex(double,double)
conjugate(=complex("3+4i")) = complex("3-4i"). % alternatively, use constructor complex(string)
In effect, importing the type complex also tells Dyna that complex(...) is a computed expression. Evaluating a complex(...) term calls the C++ function complex (actually a constructor in this case, so it returns a complex value).
- Note the use of the
=subtermsyntax for replacing a subterm with its value. Should link to documentation of this. However, this syntax is not yet implemented or stable. See expression.
It is also possible to use Dyna's function mechanism to import other C++ functions that return useful complex values. For example,
:- function(i).
says that that any structure whose functor is i should be evaluated by calling the C++ function i. This allows you to write
:- complex(=3+4*i) = 3-4*i.
and the value of i will be obtained by calling the C++ function i() with no arguments. This technique is also handy for defining constants of non-imported types; e.g., you could write a C++ function pi() that returns a double, and tell Dyna about it via
:- function(pi).
- Perhaps this 0-argument case should be handled by a static constant on the C++ instead of a function, just as in the other direction, the generated code for 0-ary structures produces static constants.
Note: You might never need to call a constructor in a Dyna program. Even if you use imported types, it is quite possible that you will construct new instances only in your C++ driver program:
c.assertval(conjugate(complex(3,4)), complex(3,-4)).
One exception is that if you want to have complex-valued items, your Dyna program will need to specify a complex default value, as in the above declaration :- item(conjugate, complex, complex(0,0)).
- Alternatively, perhaps Dyna could allow
:- item(conjugate, complex)to fill in its missing third argument from thecomplexclass somehow. But it's not appropriate to get this argument from the null constructorcomplex()(which may do no initialization at all). So the user would presumably have to write extra C++ definitions such asdyna_default<complex>."
