Lecture 9: Programming Language Semantics Programming Languages Course Aarne Ranta (aarne@cs.chalmers.se) %!target:html %!postproc(html): #NEW %!postproc(html): #HR
%!postproc(html): #sub1 1 %!postproc(html): #subn n %!postproc(html): #subn1 n-1 Book: #NEW ==Plan== What is semantics? What is meaning? Operational semantics: small-step Operational semantics: big-step Abstract interprerations Up to here, we follow [another set of slides ./proglang-09.pdf] with a nice notation and lay-out, by Ulf Norell, pp. 1-19. Next time: from semantics to interpreter implementation This time: case study on small-step semantics: JVM #NEW ==Java bytecode interpretation== Byte code, virtual machine code - simpler than high-level source code. Example: JVM (Java Virtual Machine) ``` bipush n -- push byte constant n iadd -- add two integers; pop the operands and push the result imul -- multiply two integers; pop the operands and push the result istore x -- store value in stack address x and pop it iload x -- push value to stack address x dup -- duplicate the top of the stack invokestatic -- call a function with parameters from the top of the stack, pop the parameters and push the value ``` Java is compiled to JVM (next lecture). JVM is interpreted, or compiled to native machine code by JIT (Just In Time compilation). Most "interpreted languages" are actually compiled to byte code. Exception: Ruby. Example use of ``invokestatic``, generated from ``printInt(5)``: ``` bipush 5 invokestatic runtime/iprint(I)V ``` The type ``(I)V`` tells e.g. how many values to pop. #NEW ==JVM interpreter== Environment: **local variable storage** and a **stack** holding values Primitive actions: - **store** value in place #i in local storage - **load** value from place #i in local storage - **push** a value to the stack - **pop** a value from the stack Example execution: ``5 * (6 + 7)`` ``` bipush 5 ; bipush 6 ; bipush 7 ; iadd ; imul -- -- -- -- -- 5 5 5 5 65 6 6 13 7 ``` #NEW ==Local variables in JVM== The compiler assigns local storage addresses to variables (lecture 11). ``` int i ; ; reserve address 0 for i i = 9 ; bipush 9 istore 0 int j = i + 3 ; ; reserve address 1 for j iload 0 bipush 3 iadd istore 1 ``` #NEW ==Semantics of JVM== Naturally expressed using small-step semantics. The environment has storage V and stack S. The rules work on instructions, executed one at a time. ``` --> --> --> --> --> --> --> ``` Notation used: || Notation | Explanation || | ```` | instruction ``c``, with storage ``V`` and stack ``S`` | | ``S.v`` | stack with all values in ``S`` plus ``v`` on the top | | ``V(i)`` | the value at position ``i`` in storage ``V`` | | ``V(i:=v)`` | storage ``V`` with value ``v`` put into position ``i`` | #NEW ==Dealing with jumps== JVM does not always continue with the next instruction, but there can be jumps. Example (my first BASIC program): ``` BEGIN: bipush 66 invokestatic runtime/iprint(I)V goto BEGIN ``` To give semantics to the ``goto`` instruction, we have to add the code ``C`` to the environment. We denote by ``C(p)`` the instruction at position ``p`` in ``C``. ``` --> ``` Question: How do we now express rules for the "ordinary" instructions? ``` --> ``` Answer: we add a code pointer ``P`` to the environment: ``` --> --> ```