compiler construction - Scheme interpreter in Go -


i'm quite basic go programmer , i've been taking @ small scheme interpreter , i've been trying understand how works.

i found here: https://pkelchte.wordpress.com/2013/12/31/scm-go/

i read webpage, i'm still struggling understand how works because source code written who's lot more familiar go am.

particularly there's these lines i'm struggling understand:

e := expression.(type) // line 73 

i'm not sure .(type) part means, thought casting doesn't casting i've seen before.

switch p := procedure.(type) { case func(...scmer) scmer:     value = p(args...) case proc:     en := &env{make(vars), p.en}     switch params := p.params.(type) {     case []scmer:         i, param := range params {             en.vars[param.(symbol)] = args[i]         }     default:         en.vars[params.(symbol)] = args     }     value = eval(p.body, en) 

i don't understand of code honest. lines 73 - 86

*tokens = (*tokens)[1:] // line 208 

i'm not sure line means due it's weird syntax. pointers , parenthesises because of *. i'm not sure lines doing.

finally there's these lines:

token := (*tokens)[0] *tokens = (*tokens)[1:] switch token { case "(": //a list begins     l := make([]scmer, 0)     (*tokens)[0] != ")" {         if := readfrom(tokens); != symbol("") {             l = append(l, i)         }     }     *tokens = (*tokens)[1:]     return l 

i don't know these lines either. lines 198 - 209

here's complete code if want it, realise it's 250 lines long i'd appreciate many explanations doing possible.

/*  * minimal scheme interpreter, seen in lis.py , sicp  * http://norvig.com/lispy.html  * http://mitpress.mit.edu/sicp/full-text/sicp/book/node77.html  *  * pieter kelchtermans 2013  * license: wtfpl 2.0  */ package main  import (     "bufio"     "fmt"     "log"     "os"     "reflect"     "strconv"     "strings" )  func main() {     repl() }  /*  eval / apply */  func eval(expression scmer, en *env) (value scmer) {     switch e := expression.(type) {     case number:         value = e     case symbol:         value = en.find(e).vars[e]     case []scmer:         switch car, _ := e[0].(symbol); car {         case "quote":             value = e[1]         case "if":             if eval(e[1], en).(bool) {                 value = eval(e[2], en)             } else {                 value = eval(e[3], en)             }         case "set!":             v := e[1].(symbol)             en.find(v).vars[v] = eval(e[2], en)             value = "ok"         case "define":             en.vars[e[1].(symbol)] = eval(e[2], en)             value = "ok"         case "lambda":             value = proc{e[1], e[2], en}         case "begin":             _, := range e[1:] {                 value = eval(i, en)             }         default:             operands := e[1:]             values := make([]scmer, len(operands))             i, x := range operands {                 values[i] = eval(x, en)             }             value = apply(eval(e[0], en), values)         }     default:         log.println("unknown expression type - eval", e)     }     return }  func apply(procedure scmer, args []scmer) (value scmer) {     switch p := procedure.(type) {     case func(...scmer) scmer:         value = p(args...)     case proc:         en := &env{make(vars), p.en}         switch params := p.params.(type) {         case []scmer:             i, param := range params {                 en.vars[param.(symbol)] = args[i]             }         default:             en.vars[params.(symbol)] = args         }         value = eval(p.body, en)     default:         log.println("unknown procedure type - apply", p)     }     return }  type proc struct {     params, body scmer     en           *env }  /*  environments */  type vars map[symbol]scmer type env struct {     vars     outer *env }  func (e *env) find(s symbol) *env {     if _, ok := e.vars[s]; ok {         return e     } else {         return e.outer.find(s)     } }  /*  primitives */  var globalenv env  func init() {     globalenv = env{         vars{ //aka incomplete set of compiled-in functions             "+": func(a ...scmer) scmer {                 v := a[0].(number)                 _, := range a[1:] {                     v += i.(number)                 }                 return v             },             "-": func(a ...scmer) scmer {                 v := a[0].(number)                 _, := range a[1:] {                     v -= i.(number)                 }                 return v             },             "*": func(a ...scmer) scmer {                 v := a[0].(number)                 _, := range a[1:] {                     v *= i.(number)                 }                 return v             },             "/": func(a ...scmer) scmer {                 v := a[0].(number)                 _, := range a[1:] {                     v /= i.(number)                 }                 return v             },             "<=": func(a ...scmer) scmer {                 return a[0].(number) <= a[1].(number)             },             "equal?": func(a ...scmer) scmer {                 return reflect.deepequal(a[0], a[1])             },             "cons": func(a ...scmer) scmer {                 switch car := a[0]; cdr := a[1].(type) {                 case []scmer:                     return append([]scmer{car}, cdr...)                 default:                     return []scmer{car, cdr}                 }             },             "car": func(a ...scmer) scmer {                 return a[0].([]scmer)[0]             },             "cdr": func(a ...scmer) scmer {                 return a[0].([]scmer)[1:]             },             "list": eval(read(                 "(lambda z z)"),                 &globalenv),         },         nil} }  /*  parsing */  //symbols, numbers, expressions, procedures, lists, ... implement interface, enables passing them along in interpreter type scmer interface{}  type symbol string  //symbols represented strings type number float64 //numbers float64  func read(s string) (expression scmer) {     tokens := tokenize(s)     return readfrom(&tokens) }  //syntactic analysis func readfrom(tokens *[]string) (expression scmer) {     //pop first element tokens     token := (*tokens)[0]     *tokens = (*tokens)[1:]     switch token {     case "(": //a list begins         l := make([]scmer, 0)         (*tokens)[0] != ")" {             if := readfrom(tokens); != symbol("") {                 l = append(l, i)             }         }         *tokens = (*tokens)[1:]         return l     default: //an atom occurs         if f, err := strconv.parsefloat(token, 64); err == nil {             return number(f)         } else {             return symbol(token)         }     } }  //lexical analysis func tokenize(s string) []string {     return strings.split(         strings.replace(strings.replace(s, "(", "( ",             -1), ")", " )",             -1), " ") }  /*  interactivity */  func string(v scmer) string {     switch v := v.(type) {     case []scmer:         l := make([]string, len(v))         i, x := range v {             l[i] = string(x)         }         return "(" + strings.join(l, " ") + ")"     default:         return fmt.sprint(v)     } }  func repl() {     scanner := bufio.newscanner(os.stdin)     fmt.print("> "); scanner.scan(); fmt.print("> ") {         fmt.println("==>", string(eval(read(scanner.text()), &globalenv)))     } } 

first 1 type switch. can read more here.

second 1 slicing in python (if know it, should familiar)

ls = ls[1:] 

we're skipping first item , taking rest of slice/list.

as see comments, think it's not starting point experiment golang.


Comments

Popular posts from this blog

toolbar - How to add link to user registration inside toobar in admin joomla 3 custom component -

linux - disk space limitation when creating war file -