CS 3723
  Programming Languages  
  3.4 Dictionaries   

Reference links given below will be to the online book: Building skills in Python


3.4. Dictionaries See Dictionaries. These are a familiar feature in Perl and other scripting languages, called "hashes" or "associative arrays" in Perl.

First is a program that translates simple one-operand assignments for our Tiny project into MIPS assembly language. The first dictionary gives the offset corresponding to each single-character operand. This offset could be calculated with two simple formulas, but the method here is far more general and is used for illustrative purposes. Similarly, the second dictionary translates from a single-character operand to the MIPS op-code.

Translate Assigns to MIPS Output (plus exec frame)
#!/usr/bin/python
import sys
# MIPS offsets for constants and variables
d = {"0":0, "1":   8, "2":  16, "3":  24, "4":  32, 
  "5":  40, "6":  48, "7":  56, "8":  64, "9":  72, 
  "a":  80, "b":  88, "c":  96, "d": 104, "e": 112,
  "f": 120, "g": 128, "h": 136, "i": 144, "j": 152,
  "k": 160, "l": 168, "m": 176, "n": 184, "o": 192,
  "p": 200, "q": 208, "r": 216, "s": 224, "t": 232,
  "u": 240, "v": 248, "w": 256, "x": 264, "y": 272,
  "z": 280}
# MIPS opcodes for operators
op = {"+":"add", "-":"sub", "*":"mul", "/":"div"}

def instr(x):
    s = x[2]
    t = x[4]
    a = x[3]
    r = x[0]
    sys.stdout.write( "\tl.d      $f2, " +
       str(d[s]) + "($s1)\n")
    sys.stdout.write( "\tl.d      $f4, " +
       str(d[t]) + "($s1)\n")
    sys.stdout.write("\t" + str(op[a]) +
       ".d    $f6, $f2, $f4\n")
    sys.stdout.write( "\ts.d      $f6, " +
       str(d[r]) + "($s1)\n\n")
   
instr("a=8*2")
instr("b=7*a")
instr("c=b+1")
instr("d=a/c")
instr("e=3+d")
main:   addu    $s7, $ra, $zero
        la      $s1, M
        l.d      $f2, 64($s1)
        l.d      $f4, 16($s1)
        mul.d    $f6, $f2, $f4
        s.d      $f6, 80($s1)

        l.d      $f2, 56($s1)
        l.d      $f4, 80($s1)
        mul.d    $f6, $f2, $f4
        s.d      $f6, 88($s1)

        l.d      $f2, 88($s1)
        l.d      $f4, 8($s1)
        add.d    $f6, $f2, $f4
        s.d      $f6, 96($s1)

        l.d      $f2, 80($s1)
        l.d      $f4, 96($s1)
        div.d    $f6, $f2, $f4
        s.d      $f6, 104($s1)

        l.d      $f2, 24($s1)
        l.d      $f4, 104($s1)
        add.d    $f6, $f2, $f4
        s.d      $f6, 112($s1)
# Print result + newl
        li      $v0, 3
        l.d     $f12, 112($s1)
        syscall
        li      $v0, 4
        la      $a0, NewL
        syscall
# Stuff at end ################
        addu    $ra, $s7, $zero
        jr      $ra  # ret
        .data
        .align  3
M:      .double 0.,1.,2.,3.,4.
        .double 5.,6.,7.,8.,9.
        .space  208  # a to z
NewL:   .asciiz "\n"

The output of running the MIPS program is: 3.14159292035398252 ( = 355/113).

Items of Interest or for study:

  • Continuation: The definition of the dictionary d can be continued on later lines in any way at all as soon as the { appears. However, you can't start this declaration with d = as the only thing on the line but would need d = \ .

Inverting a Dictionary:

The second components have to be "hashable" for this to work. (I didn't write this code myself. I edited the output to group items together with the same precedence.)

Inverting a Dictionary
#!/usr/bin/python
# example with no duplicate 2nd components
op = {"+":"add", "-":"sub", "*":"mul", "/":"div"}
inv_op = {}
for k, v in op.items():
    inv_op[v] = k
print inv_op
# Has duplicate 2nd components (prec of C ops)
prec = {",":0,
    "=":1, "+=":1, "-=":1, "*=":1, "/=":1, "%=":1,
           "&=":1, "^=":1, "|=":1, "<<=":1, ">>=":1,
    "?:":2,
    "||":3,
    "&&":4,
    "|":5,
    "^":6,
    "&":7, 
    "==":8, "!=":8,
    "<":9, "<=":9,  ">":9, ">=": 9,
    "<<":10, ">>":10,
    "+":11,  "-":11,
    "*": 12, "/": 12,  "%":12,
    "!":13, "~":13, "++":13, "--":13, "+(u)":13,
            "-(u)":13, "*(p)":13, "&(a)":13, "(type)":13, "sizeof":13,
    "(group)":14, "[]":14, "->":14,  ".":14,} 
inv_prec = {}
for k, v in prec.iteritems():
    inv_prec[v] = inv_prec.get(v, [])
    inv_prec[v].append(k)

print inv_prec
Output
{'mul': '*', 'add': '+', 'div': '/', 'sub': '-'}

{ 0: [','],
  1: ['%=', '>>=', '|=', '-=', '^=', '<<=', '=', '*=', '&=', '/=', '+='],
  2: ['?:'],
  3: ['||'],
  4: ['&&'],
  5: ['|'],
  6: ['^'],
  7: ['&'],
  8: ['!=', '=='],
  9: ['>=', '<', '>', '<='],
 10: ['>>', '<<'],
 11: ['+', '-'],
 12: ['*', '%', '/'],
 13: ['+(u)', '&(a)', '-(u)', '--', '~', 'sizeof', '!', '(type)', '++', '*(p)'],
 14: ['[]', '.', '(group)', '->']}

(Revision date: 2014-05-24. Please use ISO 8601, the International Standard.)