x/debug: add syntax for getting the value of an arbitrary symbol in the binary.

Putting arbitrary symbol names through the parser won't work in general,
so we add a built-in function lookup("x") which gets the value of the
symbol x.

Change-Id: Ia35163fc93c0fcdf58bdaacefdc5121a61cd3aa1
Reviewed-on: https://go-review.googlesource.com/16855
Reviewed-by: jcd . <jcd@golang.org>
diff --git a/ogle/demo/ogler/ogler_test.go b/ogle/demo/ogler/ogler_test.go
index d825fc9..cab7f94 100644
--- a/ogle/demo/ogler/ogler_test.go
+++ b/ogle/demo/ogler/ogler_test.go
@@ -90,168 +90,267 @@
 // expectedEvaluate contains expected results of the program.Evaluate function.
 // A nil value indicates that an error is expected.
 var expectedEvaluate = map[string]program.Value{
-	`x`:                         int16(42),
-	`local_array`:               program.Array{42, 42, 5, 8},
-	`local_bool_false`:          false,
-	`local_bool_true`:           true,
-	`local_channel`:             program.Channel{42, 42, 42, 0, 0, 2, 0},
-	`local_channel_buffered`:    program.Channel{42, 42, 42, 6, 10, 2, 8},
-	`local_channel_nil`:         program.Channel{42, 0, 0, 0, 0, 2, 0},
-	`local_complex128`:          complex128(1.987654321 - 2.987654321i),
-	`local_complex64`:           complex64(1.54321 + 2.54321i),
-	`local_float32`:             float32(1.54321),
-	`local_float64`:             float64(1.987654321),
-	`local_func_int8_r_int8`:    program.Func{42},
-	`local_func_int8_r_pint8`:   program.Func{42},
-	`local_func_bar`:            program.Func{42},
-	`local_func_nil`:            program.Func{0},
-	`local_int`:                 -21,
-	`local_int16`:               int16(-32321),
-	`local_int32`:               int32(-1987654321),
-	`local_int64`:               int64(-9012345678987654321),
-	`local_int8`:                int8(-121),
-	`local_int_typedef`:         int16(88),
-	`local_interface`:           program.Interface{},
-	`local_interface_nil`:       program.Interface{},
-	`local_interface_typed_nil`: program.Interface{},
-	`local_map`:                 program.Map{42, 42, 1},
-	`local_map_2`:               program.Map{42, 42, 1},
-	`local_map_3`:               program.Map{42, 42, 2},
-	`local_map_empty`:           program.Map{42, 42, 0},
-	`local_map_nil`:             program.Map{42, 42, 0},
-	`local_pointer`:             program.Pointer{42, 42},
-	`local_pointer_nil`:         program.Pointer{42, 0},
-	`local_slice`:               program.Slice{program.Array{42, 42, 5, 8}, 5},
-	`local_slice_2`:             program.Slice{program.Array{42, 42, 2, 8}, 5},
-	`local_slice_nil`:           program.Slice{program.Array{42, 0, 0, 8}, 0},
-	`local_string`:              program.String{12, `I'm a string`},
-	`local_struct`:              program.Struct{[]program.StructField{{"a", program.Var{}}, {"b", program.Var{}}}},
-	`local_uint`:                uint(21),
-	`local_uint16`:              uint16(54321),
-	`local_uint32`:              uint32(3217654321),
-	`local_uint64`:              uint64(12345678900987654321),
-	`local_uint8`:               uint8(231),
-	`local_uintptr`:             uint(21),
-	`local_unsafe_pointer`:      program.Pointer{0, 42},
-	`local_unsafe_pointer_nil`:  program.Pointer{0, 0},
-	`x + 5`:                     int16(47),
-	`x - 5`:                     int16(37),
-	`x / 5`:                     int16(8),
-	`x % 5`:                     int16(2),
-	`x & 2`:                     int16(2),
-	`x | 1`:                     int16(43),
-	`x ^ 3`:                     int16(41),
-	`5 + x`:                     int16(47),
-	`5 - x`:                     int16(-37),
-	`100 / x`:                   int16(2),
-	`100 % x`:                   int16(16),
-	`2 & x`:                     int16(2),
-	`1 | x`:                     int16(43),
-	`3 ^ x`:                     int16(41),
-	`12`:                        12,
-	`+42`:                       42,
-	`23i`:                       23i,
-	`34.0`:                      34.0,
-	`34.5`:                      34.5,
-	`1e5`:                       100000.0,
-	`0x42`:                      66,
-	`'c'`:                       'c',
-	`"de"`:                      program.String{2, `de`},
-	"`ef`":                      program.String{2, `ef`},
-	`"de" + "fg"`:               program.String{4, `defg`},
-	`/* comment */ -5`:          -5,
-	`false`:                     false,
-	`true`:                      true,
-	`!false`:                    true,
-	`!true`:                     false,
-	`5 + 5`:                     10,
-	`true || false`:             true,
-	`false || false`:            false,
-	`true && false`:             false,
-	`true && true`:              true,
-	`!(5 > 8)`:                  true,
-	`10 + 'a'`:                  'k',
-	`10 + 10.5`:                 20.5,
-	`10 + 10.5i`:                10 + 10.5i,
-	`'a' + 10.5`:                107.5,
-	`'a' + 10.5i`:               97 + 10.5i,
-	`10.5 + 20.5i`:              10.5 + 20.5i,
-	`10 * 20`:                   200,
-	`10.0 - 20.5`:               -10.5,
-	`(6 + 8i) * 4`:              24 + 32i,
-	`(6 + 8i) * (1 + 1i)`:       -2 + 14i,
-	`(6 + 8i) * (6 - 8i)`:       complex128(100),
-	`(6 + 8i) / (3 + 4i)`:       complex128(2),
-	`local_string + "!"`:        program.String{13, `I'm a string!`},
-	`*local_pointer`:            program.Struct{[]program.StructField{{"a", program.Var{}}, {"b", program.Var{}}}},
-	`&local_int16`:              program.Pointer{42, 42},
-	`*&local_int16`:             int16(-32321),
-	`*&*&*&*&local_int16`:       int16(-32321),
-	`local_array[2]`:            int8(3),
-	`local_slice[1]`:            uint8(108),
-	`local_slice_2[1]`:          int8(121),
-	`&local_array[1]`:           program.Pointer{42, 42},
-	`&local_slice[1]`:           program.Pointer{42, 42},
-	`local_map[-21]`:            float32(3.54321),
-	`local_map[+21]`:            float32(0),
-	`local_map_3[1024]`:         int8(1),
-	`local_map_3[512]`:          int8(-1),
-	`local_map_empty[21]`:       float32(0),
-	`local_map_nil[32]`:         float32(0),
-	`local_string[2]`:           uint8('m'),
-	`"hello"[2]`:                uint8('l'),
-	`local_array[1:3][1]`:       int8(3),
-	`local_array[0:4][2:3][0]`:  int8(3),
-	`local_array[:]`:            program.Slice{program.Array{42, 42, 5, 8}, 5},
-	`local_array[:2]`:           program.Slice{program.Array{42, 42, 2, 8}, 5},
-	`local_array[2:]`:           program.Slice{program.Array{42, 42, 3, 8}, 3},
-	`local_array[1:3]`:          program.Slice{program.Array{42, 42, 2, 8}, 4},
-	`local_array[:3:4]`:         program.Slice{program.Array{42, 42, 3, 8}, 4},
-	`local_array[1:3:4]`:        program.Slice{program.Array{42, 42, 2, 8}, 3},
-	`local_array[1:][1:][1:]`:   program.Slice{program.Array{42, 42, 2, 8}, 2},
-	`(&local_array)[:]`:         program.Slice{program.Array{42, 42, 5, 8}, 5},
-	`(&local_array)[:2]`:        program.Slice{program.Array{42, 42, 2, 8}, 5},
-	`(&local_array)[2:]`:        program.Slice{program.Array{42, 42, 3, 8}, 3},
-	`(&local_array)[1:3]`:       program.Slice{program.Array{42, 42, 2, 8}, 4},
-	`(&local_array)[:3:4]`:      program.Slice{program.Array{42, 42, 3, 8}, 4},
-	`(&local_array)[1:3:4]`:     program.Slice{program.Array{42, 42, 2, 8}, 3},
-	`local_slice[1:5][0:3][1]`:  uint8('i'),
-	`local_slice[:]`:            program.Slice{program.Array{42, 42, 5, 8}, 5},
-	`local_slice[:2]`:           program.Slice{program.Array{42, 42, 2, 8}, 5},
-	`local_slice[2:]`:           program.Slice{program.Array{42, 42, 3, 8}, 3},
-	`local_slice[1:3]`:          program.Slice{program.Array{42, 42, 2, 8}, 4},
-	`local_slice[:3:4]`:         program.Slice{program.Array{42, 42, 3, 8}, 4},
-	`local_slice[1:3:4]`:        program.Slice{program.Array{42, 42, 2, 8}, 3},
-	`local_struct.a`:            21,
-	`(&local_struct).a`:         21,
-	`(*local_pointer).a`:        21,
-	`(&*local_pointer).a`:       21,
-	`(*local_pointer).b`:        program.String{2, `hi`},
-	`local_pointer.a`:           21,
-	`local_pointer.b`:           program.String{2, `hi`},
-	`5 + false`:                 nil,
-	``:                          nil,
-	`x + ""`:                    nil,
-	`x / 0`:                     nil,
-	`0 / 0`:                     nil,
-	`'a' / ('a'-'a')`:           nil,
-	`0.0 / 0.0`:                 nil,
-	`3i / 0.0`:                  nil,
-	`x % 0`:                     nil,
-	`0 % 0`:                     nil,
-	`'a' % ('a'-'a')`:           nil,
-	`local_array[-2] + 1`:       nil,
-	`local_array[22] + 1`:       nil,
-	`local_slice[-2] + 1`:       nil,
-	`local_slice[22] + 1`:       nil,
-	`local_string[-2]`:          nil,
-	`local_string[22]`:          nil,
-	`"hello"[-2]`:               nil,
-	`"hello"[22]`:               nil,
-	`local_pointer_nil.a`:       nil,
-	`(local_struct).c`:          nil,
-	`(&local_struct).c`:         nil,
-	`(*local_pointer).c`:        nil,
+	`x`:                                                          int16(42),
+	`local_array`:                                                program.Array{42, 42, 5, 8},
+	`local_bool_false`:                                           false,
+	`local_bool_true`:                                            true,
+	`local_channel`:                                              program.Channel{42, 42, 42, 0, 0, 2, 0},
+	`local_channel_buffered`:                                     program.Channel{42, 42, 42, 6, 10, 2, 8},
+	`local_channel_nil`:                                          program.Channel{42, 0, 0, 0, 0, 2, 0},
+	`local_complex128`:                                           complex128(1.987654321 - 2.987654321i),
+	`local_complex64`:                                            complex64(1.54321 + 2.54321i),
+	`local_float32`:                                              float32(1.54321),
+	`local_float64`:                                              float64(1.987654321),
+	`local_func_int8_r_int8`:                                     program.Func{42},
+	`local_func_int8_r_pint8`:                                    program.Func{42},
+	`local_func_bar`:                                             program.Func{42},
+	`local_func_nil`:                                             program.Func{0},
+	`local_int`:                                                  -21,
+	`local_int16`:                                                int16(-32321),
+	`local_int32`:                                                int32(-1987654321),
+	`local_int64`:                                                int64(-9012345678987654321),
+	`local_int8`:                                                 int8(-121),
+	`local_int_typedef`:                                          int16(88),
+	`local_interface`:                                            program.Interface{},
+	`local_interface_nil`:                                        program.Interface{},
+	`local_interface_typed_nil`:                                  program.Interface{},
+	`local_map`:                                                  program.Map{42, 42, 1},
+	`local_map_2`:                                                program.Map{42, 42, 1},
+	`local_map_3`:                                                program.Map{42, 42, 2},
+	`local_map_empty`:                                            program.Map{42, 42, 0},
+	`local_map_nil`:                                              program.Map{42, 42, 0},
+	`local_pointer`:                                              program.Pointer{42, 42},
+	`local_pointer_nil`:                                          program.Pointer{42, 0},
+	`local_slice`:                                                program.Slice{program.Array{42, 42, 5, 8}, 5},
+	`local_slice_2`:                                              program.Slice{program.Array{42, 42, 2, 8}, 5},
+	`local_slice_nil`:                                            program.Slice{program.Array{42, 0, 0, 8}, 0},
+	`local_string`:                                               program.String{12, `I'm a string`},
+	`local_struct`:                                               program.Struct{[]program.StructField{{"a", program.Var{}}, {"b", program.Var{}}}},
+	`local_uint`:                                                 uint(21),
+	`local_uint16`:                                               uint16(54321),
+	`local_uint32`:                                               uint32(3217654321),
+	`local_uint64`:                                               uint64(12345678900987654321),
+	`local_uint8`:                                                uint8(231),
+	`local_uintptr`:                                              uint(21),
+	`local_unsafe_pointer`:                                       program.Pointer{0, 42},
+	`local_unsafe_pointer_nil`:                                   program.Pointer{0, 0},
+	`x + 5`:                                                      int16(47),
+	`x - 5`:                                                      int16(37),
+	`x / 5`:                                                      int16(8),
+	`x % 5`:                                                      int16(2),
+	`x & 2`:                                                      int16(2),
+	`x | 1`:                                                      int16(43),
+	`x ^ 3`:                                                      int16(41),
+	`5 + x`:                                                      int16(47),
+	`5 - x`:                                                      int16(-37),
+	`100 / x`:                                                    int16(2),
+	`100 % x`:                                                    int16(16),
+	`2 & x`:                                                      int16(2),
+	`1 | x`:                                                      int16(43),
+	`3 ^ x`:                                                      int16(41),
+	`12`:                                                         12,
+	`+42`:                                                        42,
+	`23i`:                                                        23i,
+	`34.0`:                                                       34.0,
+	`34.5`:                                                       34.5,
+	`1e5`:                                                        100000.0,
+	`0x42`:                                                       66,
+	`'c'`:                                                        'c',
+	`"de"`:                                                       program.String{2, `de`},
+	"`ef`":                                                       program.String{2, `ef`},
+	`"de" + "fg"`:                                                program.String{4, `defg`},
+	`/* comment */ -5`:                                           -5,
+	`false`:                                                      false,
+	`true`:                                                       true,
+	`!false`:                                                     true,
+	`!true`:                                                      false,
+	`5 + 5`:                                                      10,
+	`true || false`:                                              true,
+	`false || false`:                                             false,
+	`true && false`:                                              false,
+	`true && true`:                                               true,
+	`!(5 > 8)`:                                                   true,
+	`10 + 'a'`:                                                   'k',
+	`10 + 10.5`:                                                  20.5,
+	`10 + 10.5i`:                                                 10 + 10.5i,
+	`'a' + 10.5`:                                                 107.5,
+	`'a' + 10.5i`:                                                97 + 10.5i,
+	`10.5 + 20.5i`:                                               10.5 + 20.5i,
+	`10 * 20`:                                                    200,
+	`10.0 - 20.5`:                                                -10.5,
+	`(6 + 8i) * 4`:                                               24 + 32i,
+	`(6 + 8i) * (1 + 1i)`:                                        -2 + 14i,
+	`(6 + 8i) * (6 - 8i)`:                                        complex128(100),
+	`(6 + 8i) / (3 + 4i)`:                                        complex128(2),
+	`local_string + "!"`:                                         program.String{13, `I'm a string!`},
+	`*local_pointer`:                                             program.Struct{[]program.StructField{{"a", program.Var{}}, {"b", program.Var{}}}},
+	`&local_int16`:                                               program.Pointer{42, 42},
+	`*&local_int16`:                                              int16(-32321),
+	`*&*&*&*&local_int16`:                                        int16(-32321),
+	`local_array[2]`:                                             int8(3),
+	`local_slice[1]`:                                             uint8(108),
+	`local_slice_2[1]`:                                           int8(121),
+	`&local_array[1]`:                                            program.Pointer{42, 42},
+	`&local_slice[1]`:                                            program.Pointer{42, 42},
+	`local_map[-21]`:                                             float32(3.54321),
+	`local_map[+21]`:                                             float32(0),
+	`local_map_3[1024]`:                                          int8(1),
+	`local_map_3[512]`:                                           int8(-1),
+	`local_map_empty[21]`:                                        float32(0),
+	`local_map_nil[32]`:                                          float32(0),
+	`local_string[2]`:                                            uint8('m'),
+	`"hello"[2]`:                                                 uint8('l'),
+	`local_array[1:3][1]`:                                        int8(3),
+	`local_array[0:4][2:3][0]`:                                   int8(3),
+	`local_array[:]`:                                             program.Slice{program.Array{42, 42, 5, 8}, 5},
+	`local_array[:2]`:                                            program.Slice{program.Array{42, 42, 2, 8}, 5},
+	`local_array[2:]`:                                            program.Slice{program.Array{42, 42, 3, 8}, 3},
+	`local_array[1:3]`:                                           program.Slice{program.Array{42, 42, 2, 8}, 4},
+	`local_array[:3:4]`:                                          program.Slice{program.Array{42, 42, 3, 8}, 4},
+	`local_array[1:3:4]`:                                         program.Slice{program.Array{42, 42, 2, 8}, 3},
+	`local_array[1:][1:][1:]`:                                    program.Slice{program.Array{42, 42, 2, 8}, 2},
+	`(&local_array)[:]`:                                          program.Slice{program.Array{42, 42, 5, 8}, 5},
+	`(&local_array)[:2]`:                                         program.Slice{program.Array{42, 42, 2, 8}, 5},
+	`(&local_array)[2:]`:                                         program.Slice{program.Array{42, 42, 3, 8}, 3},
+	`(&local_array)[1:3]`:                                        program.Slice{program.Array{42, 42, 2, 8}, 4},
+	`(&local_array)[:3:4]`:                                       program.Slice{program.Array{42, 42, 3, 8}, 4},
+	`(&local_array)[1:3:4]`:                                      program.Slice{program.Array{42, 42, 2, 8}, 3},
+	`local_slice[1:5][0:3][1]`:                                   uint8('i'),
+	`local_slice[:]`:                                             program.Slice{program.Array{42, 42, 5, 8}, 5},
+	`local_slice[:2]`:                                            program.Slice{program.Array{42, 42, 2, 8}, 5},
+	`local_slice[2:]`:                                            program.Slice{program.Array{42, 42, 3, 8}, 3},
+	`local_slice[1:3]`:                                           program.Slice{program.Array{42, 42, 2, 8}, 4},
+	`local_slice[:3:4]`:                                          program.Slice{program.Array{42, 42, 3, 8}, 4},
+	`local_slice[1:3:4]`:                                         program.Slice{program.Array{42, 42, 2, 8}, 3},
+	`local_struct.a`:                                             21,
+	`(&local_struct).a`:                                          21,
+	`(*local_pointer).a`:                                         21,
+	`(&*local_pointer).a`:                                        21,
+	`(*local_pointer).b`:                                         program.String{2, `hi`},
+	`local_pointer.a`:                                            21,
+	`local_pointer.b`:                                            program.String{2, `hi`},
+	`lookup("main.Z_array")`:                                     program.Array{42, 42, 5, 8},
+	`lookup("main.Z_array_empty")`:                               program.Array{42, 42, 0, 8},
+	`lookup("main.Z_bool_false")`:                                false,
+	`lookup("main.Z_bool_true")`:                                 true,
+	`lookup("main.Z_channel")`:                                   program.Channel{42, 42, 42, 0, 0, 2, 0},
+	`lookup("main.Z_channel_buffered")`:                          program.Channel{42, 42, 42, 6, 10, 2, 8},
+	`lookup("main.Z_channel_nil")`:                               program.Channel{42, 0, 0, 0, 0, 2, 0},
+	`lookup("main.Z_array_of_empties")`:                          program.Array{42, 42, 2, 0},
+	`lookup("main.Z_complex128")`:                                complex128(1.987654321 - 2.987654321i),
+	`lookup("main.Z_complex64")`:                                 complex64(1.54321 + 2.54321i),
+	`lookup("main.Z_float32")`:                                   float32(1.54321),
+	`lookup("main.Z_float64")`:                                   float64(1.987654321),
+	`lookup("main.Z_func_int8_r_int8")`:                          program.Func{42},
+	`lookup("main.Z_func_int8_r_pint8")`:                         program.Func{42},
+	`lookup("main.Z_func_bar")`:                                  program.Func{42},
+	`lookup("main.Z_func_nil")`:                                  program.Func{0},
+	`lookup("main.Z_int")`:                                       -21,
+	`lookup("main.Z_int16")`:                                     int16(-32321),
+	`lookup("main.Z_int32")`:                                     int32(-1987654321),
+	`lookup("main.Z_int64")`:                                     int64(-9012345678987654321),
+	`lookup("main.Z_int8")`:                                      int8(-121),
+	`lookup("main.Z_int_typedef")`:                               int16(88),
+	`lookup("main.Z_interface")`:                                 program.Interface{},
+	`lookup("main.Z_interface_nil")`:                             program.Interface{},
+	`lookup("main.Z_interface_typed_nil")`:                       program.Interface{},
+	`lookup("main.Z_map")`:                                       program.Map{42, 42, 1},
+	`lookup("main.Z_map_2")`:                                     program.Map{42, 42, 1},
+	`lookup("main.Z_map_3")`:                                     program.Map{42, 42, 2},
+	`lookup("main.Z_map_empty")`:                                 program.Map{42, 42, 0},
+	`lookup("main.Z_map_nil")`:                                   program.Map{42, 42, 0},
+	`lookup("main.Z_pointer")`:                                   program.Pointer{42, 42},
+	`lookup("main.Z_pointer_nil")`:                               program.Pointer{42, 0},
+	`lookup("main.Z_slice")`:                                     program.Slice{program.Array{42, 42, 5, 8}, 5},
+	`lookup("main.Z_slice_2")`:                                   program.Slice{program.Array{42, 42, 2, 8}, 5},
+	`lookup("main.Z_slice_nil")`:                                 program.Slice{program.Array{42, 0, 0, 8}, 0},
+	`lookup("main.Z_string")`:                                    program.String{12, `I'm a string`},
+	`lookup("main.Z_struct")`:                                    program.Struct{[]program.StructField{{"a", program.Var{}}, {"b", program.Var{}}}},
+	`lookup("main.Z_uint")`:                                      uint(21),
+	`lookup("main.Z_uint16")`:                                    uint16(54321),
+	`lookup("main.Z_uint32")`:                                    uint32(3217654321),
+	`lookup("main.Z_uint64")`:                                    uint64(12345678900987654321),
+	`lookup("main.Z_uint8")`:                                     uint8(231),
+	`lookup("main.Z_uintptr")`:                                   uint(21),
+	`lookup("main.Z_unsafe_pointer")`:                            program.Pointer{0, 42},
+	`lookup("main.Z_unsafe_pointer_nil")`:                        program.Pointer{0, 0},
+	`lookup("main.Z_int") + lookup("main.Z_int")`:                -42,
+	`lookup("main.Z_int16") < 0`:                                 true,
+	`lookup("main.Z_uint32") + lookup("main.Z_uint32")`:          uint32(2140341346),
+	`lookup("main.Z_bool_true") || lookup("main.Z_bool_false")`:  true,
+	`lookup("main.Z_bool_true") && lookup("main.Z_bool_false")`:  false,
+	`lookup("main.Z_bool_false") || lookup("main.Z_bool_false")`: false,
+	`!lookup("main.Z_bool_true")`:                                false,
+	`!lookup("main.Z_bool_false")`:                               true,
+	`lookup("main.Z_array")[2]`:                                  int8(3),
+	`lookup("main.Z_array")[1:3][1]`:                             int8(3),
+	`lookup("main.Z_array")[0:4][2:3][0]`:                        int8(3),
+	`lookup("main.Z_array_of_empties")[0]`:                       program.Struct{},
+	`lookup("main.Z_complex128") * 10.0`:                         complex128(19.87654321 - 29.87654321i),
+	`lookup("main.Z_complex64") * 0.1`:                           complex64(0.154321 + 0.254321i),
+	`lookup("main.Z_float32") * 10.0`:                            float32(15.4321),
+	`lookup("main.Z_float64") * 0.1`:                             float64(0.1987654321),
+	`lookup("main.Z_int") + 1`:                                   int(-20),
+	`lookup("main.Z_int16") - 10`:                                int16(-32331),
+	`lookup("main.Z_int32") / 10`:                                int32(-198765432),
+	`lookup("main.Z_int64") / 10`:                                int64(-901234567898765432),
+	`lookup("main.Z_int8") + 10`:                                 int8(-111),
+	`lookup("main.Z_map")[-21]`:                                  float32(3.54321),
+	`lookup("main.Z_map")[+21]`:                                  float32(0),
+	`lookup("main.Z_map_empty")[21]`:                             float32(0),
+	`lookup("main.Z_slice")[1]`:                                  uint8(108),
+	`lookup("main.Z_slice_2")[1]`:                                int8(121),
+	`lookup("main.Z_slice")[1:5][0:3][1]`:                        uint8('i'),
+	`lookup("main.Z_array")[1:3:4]`:                              program.Slice{program.Array{42, 42, 2, 8}, 3},
+	`(&lookup("main.Z_array"))[1:3:4]`:                           program.Slice{program.Array{42, 42, 2, 8}, 3},
+	`lookup("main.Z_string") + "!"`:                              program.String{13, `I'm a string!`},
+	`lookup("main.Z_struct").a`:                                  21,
+	`(&lookup("main.Z_struct")).a`:                               21,
+	`lookup("main.Z_uint")/10`:                                   uint(2),
+	`lookup("main.Z_uint16")/10`:                                 uint16(5432),
+	`lookup("main.Z_uint32")/10`:                                 uint32(321765432),
+	`lookup("main.Z_uint64")/10`:                                 uint64(1234567890098765432),
+	`lookup("main.Z_uint8")/10`:                                  uint8(23),
+	`lookup("main.Z_pointer").a`:                                 21,
+	`(*lookup("main.Z_pointer")).a`:                              21,
+	`(&*lookup("main.Z_pointer")).a`:                             21,
+	`lookup("main.Z_pointer").b`:                                 program.String{2, `hi`},
+	`(*lookup("main.Z_pointer")).b`:                              program.String{2, `hi`},
+	`(&*lookup("main.Z_pointer")).b`:                             program.String{2, `hi`},
+	`lookup("main.Z_map_nil")[32]`:                               float32(0),
+	`&lookup("main.Z_int16")`:                                    program.Pointer{42, 42},
+	`&lookup("main.Z_array")[1]`:                                 program.Pointer{42, 42},
+	`&lookup("main.Z_slice")[1]`:                                 program.Pointer{42, 42},
+	`*&lookup("main.Z_int16")`:                                   int16(-32321),
+	`*&*&*&*&lookup("main.Z_int16")`:                             int16(-32321),
+	`lookup("time.Local")`:                                       program.Pointer{42, 42},
+	`5 + false`:                                                  nil,
+	``:                                                           nil,
+	`x + ""`:                                                     nil,
+	`x / 0`:                                                      nil,
+	`0 / 0`:                                                      nil,
+	`'a' / ('a'-'a')`:                                            nil,
+	`0.0 / 0.0`:                                                  nil,
+	`3i / 0.0`:                                                   nil,
+	`x % 0`:                                                      nil,
+	`0 % 0`:                                                      nil,
+	`'a' % ('a'-'a')`:                                            nil,
+	`local_array[-2] + 1`:                                        nil,
+	`local_array[22] + 1`:                                        nil,
+	`local_slice[-2] + 1`:                                        nil,
+	`local_slice[22] + 1`:                                        nil,
+	`local_string[-2]`:                                           nil,
+	`local_string[22]`:                                           nil,
+	`"hello"[-2]`:                                                nil,
+	`"hello"[22]`:                                                nil,
+	`local_pointer_nil.a`:                                        nil,
+	`(local_struct).c`:                                           nil,
+	`(&local_struct).c`:                                          nil,
+	`(*local_pointer).c`:                                         nil,
+	`lookup("not a real symbol")`:                                nil,
+	`lookup("x")`:                                                nil,
+	`lookup(x)`:                                                  nil,
+	`lookup(42)`:                                                 nil,
 }
 
 func isHex(r uint8) bool {
diff --git a/ogle/program/server/eval.go b/ogle/program/server/eval.go
index 72c3f56..51e8a28 100644
--- a/ogle/program/server/eval.go
+++ b/ogle/program/server/eval.go
@@ -102,6 +102,13 @@
 // the type of the slice's elements, not the type of the slice.
 type sliceOf program.Slice
 
+// ident is a value for representing a special identifier.
+type ident string
+
+// identLookup is a built-in function of the expression evaluator which gets the
+// value of a global symbol.
+var identLookup ident = "lookup"
+
 // evalExpression evaluates a Go expression.
 // If the program counter and stack pointer are nonzero, they are used to determine
 // what local variables are available and where in memory they are.
@@ -234,6 +241,8 @@
 			return result{nil, true}
 		case "false":
 			return result{nil, false}
+		case "lookup":
+			return result{nil, identLookup}
 		}
 		return e.err("unknown identifier")
 
@@ -604,6 +613,29 @@
 			return e.err("invalid slice expression")
 		}
 
+	case *ast.CallExpr:
+		// Only supports lookup("x"), which gets the value of a global symbol x.
+		fun := e.evalNode(n.Fun, false)
+		var args []result
+		for _, a := range n.Args {
+			args = append(args, e.evalNode(a, false))
+		}
+		if fun.v == identLookup {
+			if len(args) != 1 {
+				return e.err("lookup should have one argument")
+			}
+			ident, ok := args[0].v.(untString)
+			if !ok {
+				return e.err("argument for lookup should be a string constant")
+			}
+			if a, t := e.server.findGlobalVar(string(ident)); t == nil {
+				return e.err("symbol not found")
+			} else {
+				return e.resultFrom(a, t, getAddress)
+			}
+		}
+		return e.err("function calls not implemented")
+
 	case *ast.UnaryExpr:
 		if n.Op == token.AND {
 			x := e.evalNode(n.X, true)
diff --git a/ogle/program/server/eval.m4 b/ogle/program/server/eval.m4
index 8540ba5..ec48880 100644
--- a/ogle/program/server/eval.m4
+++ b/ogle/program/server/eval.m4
@@ -102,6 +102,13 @@
 // the type of the slice's elements, not the type of the slice.
 type sliceOf program.Slice
 
+// ident is a value for representing a special identifier.
+type ident string
+
+// identLookup is a built-in function of the expression evaluator which gets the
+// value of a global symbol.
+var identLookup ident = "lookup"
+
 // evalExpression evaluates a Go expression.
 // If the program counter and stack pointer are nonzero, they are used to determine
 // what local variables are available and where in memory they are.
@@ -234,6 +241,8 @@
 			return result{nil, true}
 		case "false":
 			return result{nil, false}
+		case "lookup":
+			return result{nil, identLookup}
 		}
 		return e.err("unknown identifier")
 
@@ -604,6 +613,29 @@
 			return e.err("invalid slice expression")
 		}
 
+	case *ast.CallExpr:
+		// Only supports lookup("x"), which gets the value of a global symbol x.
+		fun := e.evalNode(n.Fun, false)
+		var args []result
+		for _, a := range n.Args {
+			args = append(args, e.evalNode(a, false))
+		}
+		if fun.v == identLookup {
+			if len(args) != 1 {
+				return e.err("lookup should have one argument")
+			}
+			ident, ok := args[0].v.(untString)
+			if !ok {
+				return e.err("argument for lookup should be a string constant")
+			}
+			if a, t := e.server.findGlobalVar(string(ident)); t == nil {
+				return e.err("symbol not found")
+			} else {
+				return e.resultFrom(a, t, getAddress)
+			}
+		}
+		return e.err("function calls not implemented")
+
 	case *ast.UnaryExpr:
 		if n.Op == token.AND {
 			x := e.evalNode(n.X, true)