Implementasi VendisScript
di Python
Oleh: Irsyad Asyhari Lubis
Apa itu VendisScript?
is a scripting language
A scripting language or script language is a
programming language that supports the writing
of scripts, programs written f...
Typically, a scripting language is characterized by
the following properties:
● Ease of use.
● OS facilities - especially ...
Typically, a scripting language is characterized by
the following properties:
● Ease of use.
● OS facilities - especially ...
is interpreted scripting language
An interpreted language is a programming
language that avoids explicit program compilation.
The interpreter executes the p...
is embedded, interpreted scripting language
sorry, no reference this time...
used in Android based mobile sales and
distribution software
why not Python?
compared to Python, VendisScript is...
simple
in term of implementation
too simple...
no optimization
no optimization (yet)
but, there is one reason to rule them all
size
it does matter!
less why...
more how...
now we are talking about implementation
in Python
note that...
scripting language on top of Python is generally
not necessary
unless it is DSL
since this is only emulator...
Apa itu VendisScript?
JSON + Lisp
JSON
{
    "firstName": "John",
    "lastName": "Smith",
    "age": 25,
    "address": {
        "streetAddress": "21 2nd Stree...
Lisp
(defun factorial (n)
   (if (<= n 1)
       1
       (* n (factorial (­ n 1)))))
Sumber: https://en.wikipedia.org/wiki/Lis...
Basic syntax
[
{
  "d": "Gratis 5 produk A untuk setiap pembelian 100 produk A.",
  "i": ["and",
         ["has", "11112313", "@product...
[
{
  "d": "Gratis 5 produk A untuk setiap pembelian 100 produk A.",
  "i": ["and",
         ["has", "11112313", "@product...
{
"d": "Test factorial.",
"i": true,
"o": ["prog",
["setq", "fac", 
["lambda", ["x"],
["cond",
["<=", "@x", 1], 1,
true, [...
{
"d": "Test factorial.",
"i": true,
"o": ["prog",
["setq", "fac", 
["lambda", ["x"],
["cond",
["<=", "@x", 1], 1,
true, [...
def fac(x):
if x <= 1:
return 1
else:
return x * fac(x ­ 1) 
[
{
“d”: @description(str),
“i”: @input(JSON),
“o”: @output(JSON)
},
...
]
Demo
Compiler Stack
Source
Code
Lexer Parser AST
Target
Code
Grammar
prog : ('[' item (',' item)* ']' | '[' ']') EOF;
item : '{' '"d"' ':' QUOTED_IDENTIFIER ',' '"i"' ':' expr ',' 
'"o"' ':' ...
let_expr : '[' '"let"' ',' '[' init_list* ']' ',' body ']';
setq_expr : '[' '"setq"' ',' QUOTED_IDENTIFIER ',' expr ']';
i...
VAR_ACCESS : '"@' IDENTIFIER '"';
QUOTED_IDENTIFIER : '"' IDENTIFIER '"';
INT : '­'? INT_WITHOUT_PREFIX;
FLOAT : '­'? INT_...
Lexer
JSON's lexer + parser
Parser
AST
1 + (2 * 3)
["+", 1, ["*", 2, 3]]
+
1 *
2 3
class Expression(object):
def __init__(self, args=None):
self.args = args if args else []
def evaluate(self, env):
pass
+
1 *
2 3
AddExpression
MulExpressionIntExpression
IntExpression IntExpression
class IntExpression(Expression):
    def __init__(self, value):
        self.value = value
    def evaluate(self, env):
  ...
class AddExpression(BasicMathExpression):
    def evaluate(self, env):
        return self._evaluate(env, 'Add', lambda x,...
class MulExpression(BasicMathExpression):
    def evaluate(self, env):
        return self._evaluate(env, 'Mul', lambda x,...
Tipe data
✔ Integer → ­1 0 1 2
✔ Float → ­2.0 1.2 2.3
✔ String → "This is a string"
✔ List → ["list", 1, 2, 3.0, 
 "This is a string...
Cons
["cons", 1, ["cons", 2, ["cons", 3, "#nil"]]]
["list", 1, 2, 3]
( head tail )
( head ( head tail ) )
( head ( head ( head tail ) ) )
( head ( head ( head nil ) ) )
class Cons(object):
    def __init__(self, head=None, tail=None):
        self._head = head
        self._tail = tail
    ...
    @staticmethod
    def from_seq(seq):
        if not seq:
            return None
        head = Cons(seq[0])
        c...
    def each(self, f):
        f(self.head)
        tail = self.tail
        while tail != None:
            if isinstance...
def map(self, f):
pass
def filter(self, f):
pass
def reduce(self, f, *args):
pass
Scope
Dynamic Scope vs Lexical Scope
Dynamic Scope vs Lexical Scope
two constructs to introduce a variable
["setq", "variable1", 100]
["let", [["variable1", 100]]
["print", "@variable1"]]
function's paramenters also introduce local
variables
{
"d": "Test factorial.",
"i": true,
"o": ["prog",
["setq", "fac", 
["lambda", ["x"],
["cond",
["<=", "@x", 1], 1,
true, [...
class BonusEnvironment(dict):
    def __init__(self, parent=None):
        self._parent = parent
    def __getitem__(self,...
class GetValExpression(Expression):
    def evaluate(self, env):
        name = self._evaluated_args(env, 
               ...
Functions
63 builtin functions
["setq", "fib",
["lambda", ["n"],
["cond",
["<", "@n", 2], 1,
true, ["+", ["fib", ["­", "@n", 1]],
["fib", ["­", "@n", 2]]...
class LambdaExpression(Expression):
    def __init__(self, params, body):
        self.params = params
        self.body =...
class ApplyExpression(Expression):
    def __init__(self, funcName, args):
        self.funcName = funcName
        self.a...
how to add new builtin function?
it should be easy, right?
Demo
Regrets
should not use None as value
class NilType(object):
def __nonzero__(self):
return False
Nil = NilType()
Thank you!!!
Implementasi VendisScript di Python
Implementasi VendisScript di Python
Implementasi VendisScript di Python
Implementasi VendisScript di Python
Upcoming SlideShare
Loading in …5
×

Implementasi VendisScript di Python

310 views
253 views

Published on

VendisScript's emulator implementation in Python. Describes how to implement a simple scripting language such as VendisScript in Python.

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
310
On SlideShare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
3
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Implementasi VendisScript di Python

  1. 1. Implementasi VendisScript di Python Oleh: Irsyad Asyhari Lubis
  2. 2. Apa itu VendisScript?
  3. 3. is a scripting language
  4. 4. A scripting language or script language is a programming language that supports the writing of scripts, programs written for a special runtime environment that can interpret and automate the execution of tasks which could alternatively be executed one-by-one by a human operator. Sumber: http://en.wikipedia.org/wiki/Scripting_language
  5. 5. Typically, a scripting language is characterized by the following properties: ● Ease of use. ● OS facilities - especially filesystem and related, built in with easy interfaces. ● Interpreted from source code - to give the fastest turnaround from script to execution. ● Relatively loose structure. Sumber: http://en.wikipedia.org/wiki/Scripting_language
  6. 6. Typically, a scripting language is characterized by the following properties: ● Ease of use. ● OS facilities - especially filesystem and related, built in with easy interfaces. ● Interpreted from source code - to give the fastest turnaround from script to execution. ● Relatively loose structure. Sumber: http://en.wikipedia.org/wiki/Scripting_language
  7. 7. is interpreted scripting language
  8. 8. An interpreted language is a programming language that avoids explicit program compilation. The interpreter executes the program source code directly, statement by statement, as a processor or scripting engine does. This can be contrasted with compiled language programs, which the user must explicitly translate into a lower-level machine language executable. Sumber: http://en.wikipedia.org/wiki/Interpreted_language
  9. 9. is embedded, interpreted scripting language
  10. 10. sorry, no reference this time...
  11. 11. used in Android based mobile sales and distribution software
  12. 12. why not Python?
  13. 13. compared to Python, VendisScript is...
  14. 14. simple
  15. 15. in term of implementation
  16. 16. too simple...
  17. 17. no optimization
  18. 18. no optimization (yet)
  19. 19. but, there is one reason to rule them all
  20. 20. size
  21. 21. it does matter!
  22. 22. less why... more how...
  23. 23. now we are talking about implementation
  24. 24. in Python
  25. 25. note that...
  26. 26. scripting language on top of Python is generally not necessary
  27. 27. unless it is DSL
  28. 28. since this is only emulator...
  29. 29. Apa itu VendisScript?
  30. 30. JSON + Lisp
  31. 31. JSON
  32. 32. {     "firstName": "John",     "lastName": "Smith",     "age": 25,     "address": {         "streetAddress": "21 2nd Street",         "city": "New York",         "state": "NY",         "postalCode": 10021     },     "phoneNumbers": [         {             "type": "home",             "number": "212 555­1234"         },         {             "type": "fax",             "number": "646 555­4567"         }     ] } Sumber: http://en.wikipedia.org/wiki/JSON
  33. 33. Lisp
  34. 34. (defun factorial (n)    (if (<= n 1)        1        (* n (factorial (­ n 1))))) Sumber: https://en.wikipedia.org/wiki/Lisp_(programming_language)
  35. 35. Basic syntax
  36. 36. [ {   "d": "Gratis 5 produk A untuk setiap pembelian 100 produk A.",   "i": ["and",          ["has", "11112313", "@products"],          [">=",             ["bulk­qty", ["take", "11112313", "@products"]],             100.0]],   "o": ["setq", "bonuses",          ["add­bonus",            ["bonus­new", "11112313",              ["floatp", ["*", ["intp",                 ["/", ["bulk­qty", ["take", "11112313",  "@products"]], 100.0]], 5]],               "PCS"],               "@bonuses"]] } ]
  37. 37. [ {   "d": "Gratis 5 produk A untuk setiap pembelian 100 produk A.",   "i": ["and",          ["has", "11112313", "@products"],          [">=",             ["bulk­qty", ["take", "11112313", "@products"]],             100.0]],   "o": ["setq", "bonuses",          ["add­bonus",            ["bonus­new", "11112313",              ["floatp", ["*", ["intp",                 ["/", ["bulk­qty", ["take", "11112313",  "@products"]], 100.0]], 5]],               "PCS"],               "@bonuses"]] } ]
  38. 38. { "d": "Test factorial.", "i": true, "o": ["prog", ["setq", "fac",  ["lambda", ["x"], ["cond", ["<=", "@x", 1], 1, true, ["*", ["fac", ["­", "@x", 1]], "@x"]]]], ["fac", 3]] }
  39. 39. { "d": "Test factorial.", "i": true, "o": ["prog", ["setq", "fac",  ["lambda", ["x"], ["cond", ["<=", "@x", 1], 1, true, ["*", ["fac", ["­", "@x", 1]], "@x"]]]], ["fac", 3]] }
  40. 40. def fac(x): if x <= 1: return 1 else: return x * fac(x ­ 1) 
  41. 41. [ { “d”: @description(str), “i”: @input(JSON), “o”: @output(JSON) }, ... ]
  42. 42. Demo
  43. 43. Compiler Stack
  44. 44. Source Code Lexer Parser AST Target Code
  45. 45. Grammar
  46. 46. prog : ('[' item (',' item)* ']' | '[' ']') EOF; item : '{' '"d"' ':' QUOTED_IDENTIFIER ',' '"i"' ':' expr ','  '"o"' ':' expr '}'; expr :      | lambda_expr      | let_expr      | setq_expr      | prog_expr      | cond_expr      | apply_expr      | QUOTED_IDENTIFIER      | VAR_ACCESS      | '#nil'      | INT      | FLOAT      | 'true'      | 'false'      ; lambda_expr : '[' '"lambda"' ',' '[' params ']' ',' body ']'; params : QUOTED_IDENTIFIER (',' QUOTED_IDENTIFIER)*; body : expr ;
  47. 47. let_expr : '[' '"let"' ',' '[' init_list* ']' ',' body ']'; setq_expr : '[' '"setq"' ',' QUOTED_IDENTIFIER ',' expr ']'; init_list : '[' QUOTED_IDENTIFIER ',' expr ']'; prog_expr : '[' '"prog"' (',' expr)+ ']'; cond_expr : '[' '"cond"' (',' cond_and_expr)+ ']'; cond_and_expr : expr ',' expr; apply_expr : '[' QUOTED_IDENTIFIER (',' expr)* ']';
  48. 48. VAR_ACCESS : '"@' IDENTIFIER '"'; QUOTED_IDENTIFIER : '"' IDENTIFIER '"'; INT : '­'? INT_WITHOUT_PREFIX; FLOAT : '­'? INT_WITHOUT_PREFIX '.' [0­9]* EXP?; WS : [ tnr]+ ­> skip; fragment IDENTIFIER : (ESC | ~('"'|''))*; fragment INT_WITHOUT_PREFIX : '0'|[1­9][0­9]*; fragment EXP : [Ee][+|­]? INT_WITHOUT_PREFIX; fragment ESC : '' ('b'|'t'|'n'|'f'|'r'|'"'|''|UNICODE); fragment UNICODE : 'u' HEX HEX HEX HEX; fragment HEX : [0­9a­fA­F];
  49. 49. Lexer
  50. 50. JSON's lexer + parser
  51. 51. Parser
  52. 52. AST
  53. 53. 1 + (2 * 3)
  54. 54. ["+", 1, ["*", 2, 3]]
  55. 55. + 1 * 2 3
  56. 56. class Expression(object): def __init__(self, args=None): self.args = args if args else [] def evaluate(self, env): pass
  57. 57. + 1 * 2 3 AddExpression MulExpressionIntExpression IntExpression IntExpression
  58. 58. class IntExpression(Expression):     def __init__(self, value):         self.value = value     def evaluate(self, env):         return self.value
  59. 59. class AddExpression(BasicMathExpression):     def evaluate(self, env):         return self._evaluate(env, 'Add', lambda x, y: x + y)
  60. 60. class MulExpression(BasicMathExpression):     def evaluate(self, env):         return self._evaluate(env, 'Mul', lambda x, y: x * y)
  61. 61. Tipe data
  62. 62. ✔ Integer → ­1 0 1 2 ✔ Float → ­2.0 1.2 2.3 ✔ String → "This is a string" ✔ List → ["list", 1, 2, 3.0,   "This is a string",  ["list", 2, 3]] ✔ Empty list → "#nil" ✔ Boolean → true false ✔ Function ✔ Product
  63. 63. Cons
  64. 64. ["cons", 1, ["cons", 2, ["cons", 3, "#nil"]]]
  65. 65. ["list", 1, 2, 3]
  66. 66. ( head tail )
  67. 67. ( head ( head tail ) )
  68. 68. ( head ( head ( head tail ) ) )
  69. 69. ( head ( head ( head nil ) ) )
  70. 70. class Cons(object):     def __init__(self, head=None, tail=None):         self._head = head         self._tail = tail     @property     def head(self):         return self._head     @property     def tail(self):         return self._tail
  71. 71.     @staticmethod     def from_seq(seq):         if not seq:             return None         head = Cons(seq[0])         current = head         for item in seq[1:]:             next_cons = Cons(item)             current._tail = next_cons             current = next_cons         return head     def to_list(self):         result = []         self.each(result.append)         return result
  72. 72.     def each(self, f):         f(self.head)         tail = self.tail         while tail != None:             if isinstance(tail, Cons):                 f(tail.head)                 tail = tail.tail             else:                 f(tail)                 tail = None
  73. 73. def map(self, f): pass def filter(self, f): pass def reduce(self, f, *args): pass
  74. 74. Scope
  75. 75. Dynamic Scope vs Lexical Scope
  76. 76. Dynamic Scope vs Lexical Scope
  77. 77. two constructs to introduce a variable
  78. 78. ["setq", "variable1", 100]
  79. 79. ["let", [["variable1", 100]] ["print", "@variable1"]]
  80. 80. function's paramenters also introduce local variables
  81. 81. { "d": "Test factorial.", "i": true, "o": ["prog", ["setq", "fac",  ["lambda", ["x"], ["cond", ["<=", "@x", 1], 1, true, ["*", ["fac", ["­", "@x", 1]], "@x"]]]], ["fac", 3]] }
  82. 82. class BonusEnvironment(dict):     def __init__(self, parent=None):         self._parent = parent     def __getitem__(self, key):         if key not in self and self._parent:             return self._parent[key]         else:             return super(BonusEnvironment, self).__getitem__(key)     def set_global(self, key, value):         # by convention, global environment is whose parent          # is None.         if not self._parent:             self[key] = value         else:             self._parent.set_global(key, value)
  83. 83. class GetValExpression(Expression):     def evaluate(self, env):         name = self._evaluated_args(env,                                      'GetVal', ((str, unicode),))         try:             return env[name]         except KeyError:             # search in builtin functions             try:                 builtin_class_name = builtin_expressions[name]                 builtin_class = globals()[builtin_class_name]                 builtin_instance = builtin_class()                 return BuiltInFunction(body=builtin_instance)             except KeyError:                 return None
  84. 84. Functions
  85. 85. 63 builtin functions
  86. 86. ["setq", "fib", ["lambda", ["n"], ["cond", ["<", "@n", 2], 1, true, ["+", ["fib", ["­", "@n", 1]], ["fib", ["­", "@n", 2]]]]]]
  87. 87. class LambdaExpression(Expression):     def __init__(self, params, body):         self.params = params         self.body = body     def evaluate(self, env):         return Function(self.params, self.body)
  88. 88. class ApplyExpression(Expression):     def __init__(self, funcName, args):         self.funcName = funcName         self.args = args     def evaluate(self, env):         func = env[self.funcName]         if isinstance(func, Function):             return func.apply(env, self.args)         else:             raise ExpressionException('Apply: Cannot find function  with name {0}'.format(self.funcName))
  89. 89. how to add new builtin function?
  90. 90. it should be easy, right?
  91. 91. Demo
  92. 92. Regrets
  93. 93. should not use None as value
  94. 94. class NilType(object): def __nonzero__(self): return False
  95. 95. Nil = NilType()
  96. 96. Thank you!!!

×