What is the type of `main0` function? - ats

What is the type of main0 function?
I'm writing gtk3 library. However the g_application_run() function needs argv.
Of course, ATS language can use argv on main0 function. But what is the type?

The following code is declared in prelude/basics_dyn.dats:
//
symintr main0
//
fun
main_void_0
((*void*)): void = "ext#mainats_void_0"
fun
main_argc_argv_0
{n:int | n >= 1}
(argc: int n, argv: !argv(n)): void = "ext#mainats_argc_argv_0"
//
overload main0 with main_void_0
overload main0 with main_argc_argv_0
//
As you can see, main0 is overloaded with main_void_0 and main_argc_argv_0. The type argv(n) is essentially for a linear string array of size n that ends with the null value. Note that the null value is not counted as part of the size.

Related

Can generators be used for JIT during development?

What is the best strategy for development in HALIDE?
The end usage will be Ahead of time compiled using generators.
Is there a way to invoke the functions defined in generator for JIT?
Thanks
Yes, Generators work just fine with JIT code.
In general, Generators are the preferred way to encapsulate individual chunk of Halide for reuse. Until recently, they were a bit awkward to use in JIT mode, but recent changes that added machine-generated Stubs greatly simplify that and make using Generators in either JIT or AOT pretty simple.
Unforunately, Generator Stubs are new enough that they aren't represented in the Tutorial yet; your best bet is to look at the self-tests in tests/generator for examples (specifically, example_jittest.cpp and stubtest_jittest.cpp).
As an overview: The basic idea of a Generator Stub is that it's a machine-generated C++ class that is created based on the Generator's public description. It doesn't do anything that you couldn't do yourself directly, but it does make Generator usage much terser, simpler, and less error-prone.
To produce a a Generator stub, just modify you your Makefile to add cpp_stub to the Generator's -e commandline flag , e.g.
./example.generator -n Example -o ./bin -e cpp_stub
This will emit a C++ source file file named example.stub.h; inside this file you'll find a C++ class that looks something like this:
class Example : public Halide::Internal::GeneratorStub {
public:
struct Inputs {
// One field per input to the Generator;
// Buffer inputs will be Halide::Funcs,
// all other (scalar) inputs will be HalideExprs
};
struct GeneratorParams {
// One field per GeneratorParam in the Generator
};
struct ScheduleParams {
// One field per GeneratorParam in the Generator
};
Example();
Example(
const GeneratorContext* context,
const Inputs& inputs,
const GeneratorParams& params = GeneratorParams()
);
void schedule(const ScheduleParams& params = ScheduleParams());
// Output(s)
Func output;
// If the Generator has multiple Outputs, they will be here too
};
You can use this Stub inside JIT code as though it were a helper function (well, mostly):
#include "example.stub.h"
Example::Inputs inputs = { ... };
auto gen = Example(context, inputs);
gen.schedule();
Halide::Buffer<int32_t> img = gen.realize(kSize, kSize, 3);
Under the hood, the Stub is constructing an instance of your Generator, filling in the Input parameters (based on the Inputs struct you give it), calling the generate() method to produce the Output Funcs, and returning them to you.
Stub usage is woefully underdocumented as I type this; I've just opened an issue to gather up the documentation and examples we have into something that is more helpful to general Halide users.
Define your Halide code in an isolated function that takes Expr and Func parameters and returns a Func. Alternatively, you can pass an output Func parameter:
In thing.h
Func thing1( Func input, Expr param1, Expr param2 );
void thing2( Func input, Expr param1, Expr param2, Func output );
In thing.cpp
Func thing1( Func input, Expr param1, Expr param2 )
{
Var x("x"), y("y");
Func output("output");
output( x, y ) = input( x, y ) * param1 + param2;
return output;
}
void thing2( Func input, Expr param1, Expr param2, Func output )
{
Var x("x"), y("y");
output( x, y ) = input( x, y ) * param1 + param2;
}
Now you can include thing.h from both your AOT generator and JIT test.

How to create a global variable in ATS?

Basically, I am looking for something more or less equivalent to the following C code:
int theGlobalCount = 0;
int
theGlobalCount_get() { return theGlobalCount; }
void
theGlobalCount_set(int n) { theGlobalCount = n; return; }
You could use a neat trick: declare a mutable global variable, and make a ref (aka mutable reference) point to it (no GC is required to make this work!). Then, implement functions to provide access to the mutable reference.
local
var theGlobalCount_var : int = 0
val theGlobalCount = ref_make_viewptr (view# theGlobalCount_var | addr# theGlobalCount_var)
in // in of [local]
fun
theGlobalCount_get () : int = ref_get_elt (theGlobalCount)
fun
theGlobalCount_set (n: int): void = ref_set_elt (theGlobalCount, n)
end // end of [local]
Note that declarations inside local-in are visible only to code inside in-end. Therefore, neither theGlobalCount_var nor theGlobalCount are visible outside the scope of the local.
Full code: glot.io
You can also use the extvar feature to update an external global variable (declared in the target language). This is very useful if you compile ATS to a language that does not support explicit pointers (e.g., JavaScript). Here is a running example that makes use of this feature:
http://www.ats-lang.org/SERVER/MYCODE/Patsoptaas_serve.php?mycode_url=http://pastebin.com/raw/MsXhVE0A

what does the subscript operator mean in sort compare function?

struct pair{
int first;
int second;
}
vector<pair> v;
sort(v.begin(), v.end(), [](pair p1, pair p2){return p1.first < p2.first});
what does the [](pair p1, pair p2){return p1.first < p2.first} mean in sort? function pointer or anything else? I can't figure out the keywords to search.
That's a Lambda Expression and the subscript operator is what introduces it. Lambda expressions were introduced in C++11.
I couldn't put it better than the MSDN article linked above which defines a lambda expression as follows:
is a convenient way of defining an anonymous function object right at the location where it is invoked or passed as an argument to a function.
this is a lambda expresion. See example below:
void abssort(float* x, unsigned n) {
std::sort(x, x + n,
// Lambda expression begins
[](float a, float b) {
return (std::abs(a) < std::abs(b));
} // end of lambda expression
);
}
reference: https://msdn.microsoft.com/en-us/library/dd293608.aspx
the function that is being passed as a parameter does not have a "function name" - it is anonymous. This is a useful abstraction as all that is needed is the functionality that is being passed (the name does not matter).

How to create a string on the heap in D?

I'm writing a trie in D and I want each trie object have a pointer to some data, which has a non-NULL value if the node is a terminal node in the trie, and NULL otherwise. The type of the data is undetermined until the trie is created (in C this would be done with a void *, but I plan to do it with a template), which is one of the reasons why pointers to heap objects are desirable.
This requires me to eventually create my data on the heap, at which point it can be pointed to by the trie node. Experimenting, it seems like new performs this task, much as it does in C++. However for some reason, this fails with strings. The following code works:
import std.stdio;
void main() {
string *a;
string b = "hello";
a = &b;
writefln("b = %s, a = %s, *a = %s", b, a, *a);
}
/* OUTPUT:
b = hello, a = 7FFF5C60D8B0, *a = hello
*/
However, this fails:
import std.stdio;
void main() {
string *a;
a = new string();
writefln("a = %s, *a = %s", a, *a);
}
/* COMPILER FAILS WITH:
test.d(5): Error: new can only create structs, dynamic arrays or class objects, not string's
*/
What gives? How can I create strings on the heap?
P.S. If anyone writing the D compiler is reading this, the apostrophe in "string's" is a grammatical error.
Strings are always allocated on the heap. This is the same for any other dynamic array (T[], string is only an alias to type immutable(char)[]).
If you need only one pointer there are two ways to do it:
auto str = "some immutable(char) array";
auto ptr1 = &str; // return pointer to reference to string (immutable(char)[]*)
auto ptr2 = str.ptr; // return pointer to first element in string (char*)
If you need pointer to empty string, use this:
auto ptr = &"";
Remember that you can't change value of any single character in string (because they are immutable). If you want to operate on characters in string use this:
auto mutableString1 = cast(char[])"Convert to mutable."; // shouldn't be used
// or
auto mutableString2 = "Convert to mutable.".dup; // T[].dup returns mutable duplicate of array
Generally you should avoid pointers unless you absolutely know what are you doing.
From memory point of view any pointer take 4B (8B for x64 machines) of memory, but if you are using pointers to arrays then, if pointer is not null, there are 12B (+ data in array) of memory in use. 4B if from pointer and 8B are from reference to array, because array references are set of two pointers. One to first and one to last element in array.
Remember that string is just immutable(char)[]. So you don't need pointers since string is already a dynamic array.
As for creating them, you just do new char[X], not new string.
The string contents are on the heap already because strings are dynamic arrays. However, in your case, it is better to use a char dynamic array instead as you require mutability.
import std.stdio;
void main() {
char[] a = null; // redundant as dynamic arrays are initialized to null
writefln("a = \"%s\", a.ptr = %s", a, a.ptr); // prints: a = "", a.ptr = null
a = "hello".dup; // dup is required because a is mutable
writefln("a = \"%s\", a.ptr = %s", a, a.ptr); // prints: a = "hello", a.ptr = 7F3146469FF0
}
Note that you don't actually hold the array's contents, but a slice of it. The array is handled by the runtime and it is allocated on the heap.
A good reading on the subject is this article http://dlang.org/d-array-article.html
If you can only use exactly one pointer and you don't want to use the suggestions in Marmyst's answer (&str in his example creates a reference to the stack which you might not want, str.ptr loses information about the strings length as D strings are not always zero terminated) you can do this:
Remeber that you can think of D arrays (and therefore strings) as a struct with a data pointer and length member:
struct ArraySlice(T)
{
T* ptr;
size_t length;
}
So when dealing with an array the array's content is always on the heap, but the ptr/length combined type is a value type and therefore usually kept on the stack. I don't know why the compiler doesn't allow you to create that value type on the heap using new, but you can always do it manually:
import core.memory;
import std.stdio;
string* ptr;
void alloc()
{
ptr = cast(string*)GC.malloc(string.sizeof);
*ptr = "Hello World!";
}
void main()
{
alloc();
writefln("ptr=%s, ptr.ptr=%s, ptr.length=%s, *ptr=%s", ptr, ptr.ptr, ptr.length, *ptr);
}

how to rb_protect everything in ruby

I want to call ruby code from my own C code. In case an exception gets raised, I have to rb_protect the ruby code I call. rb_protect looks like this:
VALUE rb_protect(VALUE (* proc) (VALUE), VALUE data, int * state)
So proc has to be a function which takes VALUE arguments and returns VALUE. I have to call a lot of functions which do not work that way. How can I rb_protect them from raising exceptions?
I have thought of using Data_Make_Struct to wrap everything into one ruby object and call methods on it. Data_Make_Struct could itself raise an exception. How do I rb_protect Data_Make_Struct?
To use rb_protect in a flexible way (e.g., to call a Ruby function with an arbitrary numbers of arguments), pass a small dispatch function to rb_protect. Ruby requires that sizeof(VALUE) == sizeof(void*), and rb_protect blindly passes the VALUE-typed data to the dispatch function without inspecting it or modifying it. This means that you can pass whatever data you want to the dispatch function, let it unpack the data and call the appropriate Ruby method(s).
For example, to rb_protect a call to a Ruby method, you might use something like this:
#define MAX_ARGS 16
struct my_callback_stuff {
VALUE obj;
ID method_id;
int nargs;
VALUE args[MAX_ARGS];
};
VALUE my_callback_dispatch(VALUE rdata)
{
struct my_callback_stuff* data = (struct my_callback_stuff*) rdata;
return rb_funcall2(data->obj, data->method_id, data->nargs, data->args);
}
... in some other function ...
{
/* need to call Ruby */
struct my_callback_stuff stuff;
stuff.obj = the_object_to_call;
stuff.method_id = rb_intern("the_method_id");
stuff.nargs = 3;
stuff.args[0] = INT2FIX(1);
stuff.args[1] = INT2FIX(2);
stuff.args[2] = INT2FIX(3);
int state = 0;
VALUE ret = rb_protect(my_callback_dispatch, (VALUE)(&stuff), &state);
if (state) {
/* ... error processing happens here ... */
}
}
Also, keep in mind that rb_rescue or rb_ensure may be a better approach for some problems.

Resources