{"action":"opened","issue":{"url":"https://api.github.com/repos/DBCG/Dataphor/issues/3","labels_url":"https://api.github.com/repos/DBCG/Dataphor/issues/3/labels{/name}","comments_url":"https://api.github.com/repos/DBCG/Dataphor/issues/3/comments","events_url":"https://api.github.com/repos/DBCG/Dataphor/issues/3/events","html_url":"https://github.com/DBCG/Dataphor/issues/3","id":107161821,"number":3,"title":"Improving  the interpreter","user":{"login":"ashalkhakov","id":1270502,"avatar_url":"https://avatars.githubusercontent.com/u/1270502?v=3","gravatar_id":"","url":"https://api.github.com/users/ashalkhakov","html_url":"https://github.com/ashalkhakov","followers_url":"https://api.github.com/users/ashalkhakov/followers","following_url":"https://api.github.com/users/ashalkhakov/following{/other_user}","gists_url":"https://api.github.com/users/ashalkhakov/gists{/gist_id}","starred_url":"https://api.github.com/users/ashalkhakov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ashalkhakov/subscriptions","organizations_url":"https://api.github.com/users/ashalkhakov/orgs","repos_url":"https://api.github.com/users/ashalkhakov/repos","events_url":"https://api.github.com/users/ashalkhakov/events{/privacy}","received_events_url":"https://api.github.com/users/ashalkhakov/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":0,"created_at":"2015-09-18T09:09:41Z","updated_at":"2015-09-18T09:09:41Z","closed_at":null,"body":"Below are some thoughts on improving the interpreter. Posting mainly for discussion.\r\n\r\nProposal 1 (on nil handling in the interpreter):\r\n\r\n1. add a new characteristic to operators, IsNilPropagating, which means that if any arguments evaluate to a nil, then the operator will also inevitably evaluate to a nil (my guess is that most operators are nil-propagating)\r\n2. use a new kind of exception (say NilException) for signalling if a nil is the result of evaluating a plan node; said exception will be catched in the following situations:\r\n  1. when storing a nil value to a variable (assignment, update/insert/delete statements)\r\n  2. when encountering a nil in a restrict (or the like), where it is considered same as false\r\n  3. when exiting the expression context (e.g. in a program `begin Foo(); Bar() end`, where Foo() is a function, a call to Foo() is evaluated and results in a nil)\r\n  4. inside if-condition, case-condition, for/while-condition, where-condition evaluation (and the like)\r\n\r\nThe upside is that a lot of repetitive conditional logic is replaced by exception handling, which should also be faster at runtime.\r\n\r\nProposal 2 (avoiding scalar type boxing when calling operators):\r\n\r\nThe PlanNode.Execute() function works only on boxed types. Avoiding boxing of return types and of arguments should improve performance considerably (by lowering GC stress).\r\n\r\n1. introduce static non-virtual Evaluate methods\r\n  1. .NET type will be along these lines: `A (Program, A1,A2,...,An)` if the operator is nil-propagating, and `MakeNullable<A> (Program, MakeNullable<A1>,MakeNullable<A2>,...,MakeNullable<An>)` if the operator is not nil-propagating, where MakeNullable<T> is just like Nullable<T> if T is a value type, and is just T otherwise, and the arrow\r\n2. for every PlanNode, keep a `Type _returnType` for the .NET type it's Evaluate method evaluates to (or, introduce TypedPlanNode<T>)\r\n3. at the CallNode, figure out if the operator's defining class defines a typed static Evaluate method (if it does, then the CallNode will invoke the method via a DynamicMethod)\r\n\r\nNote that we could probably dispense with the Nodes array in the plan node for making every node typed on its arguments.\r\n\r\nIs there a characteristic for operators which could help in deciding if Program argument is necessary for the operator to evaluate?\r\n\r\nObviously, some unboxing/boxing will still be necessary (e.g. when reading from/storing into variables).\r\n\r\nProposal 3 (avoid boxing of rows):\r\n\r\nThis one I haven't figured out yet. Currently, all rows are generically boxed (see Runtime.Data.Row and Runtime.Data.NativeRow).\r\n\r\n1. generate descendants of a Row/NativeRow which implement the existing API and typed getters/setters (currently, values are persisted as objects...)\r\n2. keep a cache somewhere that will ensure there is only one dynamic type for every DAE type\r\nhttp://www.codeproject.com/Articles/13337/Introduction-to-Creating-Dynamic-Types-with-Reflec\r\n\r\nI guess we could *specialize* some interpreter code with the exact row types?\r\n\r\n- for instance, specialize PlanNodes by the respective types of rows they can handle\r\n"}}