User Tools

Site Tools


cs330_f2016:lab16shell

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

cs330_f2016:lab16shell [2017/04/17 22:38]
dhart created
cs330_f2016:lab16shell [2021/06/30 23:42]
Line 1: Line 1:
-<file type_checker.jl>​ 
  
-# If you're getting errors about not being able to load this, you may 
-# need to add the current directory to the module load path: 
-# 
-# push!(LOAD_PATH,​ "​."​) 
-# 
-# This is how I make sure it's reloaded when something changes: 
-# workspace();​ reload("​CITypes"​);​ using CITypes 
-# 
-# This is a helper function to run through a bunch of tests in a file: 
-# CITypes.testf( "​./​tests.txt"​ ) 
-# 
- 
-module CITypes # based on the CI5 interpreter 
- 
-using Error 
-using Lexer 
-export parse, type_of_expr,​ NumType, BoolType, FunType, NListType 
- 
-# =================================================== 
- 
-abstract AE 
-abstract TypeVal 
-abstract TypeEnvironment 
- 
-# =================================================== 
- 
-# AST nodes for expressions 
- 
-type Num <: AE 
-  n::Real 
-end 
- 
-type Boolean <: AE 
-  v::Bool 
-end 
- 
-type Plus <: AE 
-  lhs::AE 
-  rhs::AE 
-end 
- 
-type Minus <: AE 
-  lhs::AE 
-  rhs::AE 
-end 
- 
-type IsZero <: AE 
-  arg::AE 
-end 
- 
-type IfB <: AE 
-  condition::​AE 
-  true_branch::​AE 
-  false_branch::​AE 
-end 
- 
-type With <: AE 
-  name::​Symbol 
-  binding_expr::​AE 
-  body::AE 
-end 
- 
-type Id <: AE 
-  name::​Symbol 
-end 
- 
-type FunDef <: AE 
-  formal_parameter::​Symbol 
-  formal_type::​TypeVal 
-  fun_body::​AE 
-end 
- 
-type FunApp <: AE 
-  fun_expr::​AE 
-  arg_expr::​AE 
-end 
- 
-type NEmpty <: AE 
-end 
- 
-type NIsEmpty <: AE 
-  list::AE 
-end 
- 
-type NCons <: AE 
-  f::AE 
-  r::AE 
-end 
- 
-type NFirst <: AE 
-  list::AE 
-end 
- 
-type NRest <: AE 
-  list::AE 
-end 
- 
-# =================================================== 
- 
-# AST nodes for types (used for type information as well) 
- 
-type NumType <: TypeVal 
-end 
- 
-type BoolType <: TypeVal 
-end 
- 
-type FunType <: TypeVal 
-  arg_type::​TypeVal 
-  result_type::​TypeVal 
-end 
- 
-type NListType <: TypeVal 
-end 
- 
-# =================================================== 
- 
-# Type Environments 
- 
-type mtTypeEnvironment <: TypeEnvironment 
-end 
- 
-type CTypeEnvironment <: TypeEnvironment 
-  name::​Symbol 
-  value::​TypeVal 
-  parent::​TypeEnvironment 
-end 
- 
-# =================================================== 
- 
-# Parser for expressions 
-# functional for valid input, doesn'​t fully reject bad input) 
- 
-function parse( expr::Real ) 
-  return Num( expr ) 
-end 
- 
-function parse( expr::Bool ) 
-  return Boolean( expr ) 
-end 
- 
-function parse( expr::​Symbol ) 
-  if expr == :nempty 
-    return NEmpty() 
-  else 
-    return Id( expr ) 
-  end 
-end 
- 
-function parse( expr::​Array{Any} ) 
- 
-  op_symbol = expr[1] 
- 
-  if op_symbol == :+ 
-    lhs = parse( expr[2] ) 
-    rhs = parse( expr[3] ) 
-    return Plus( lhs, rhs ) 
- 
-  elseif op_symbol == :- 
-    lhs = parse( expr[2] ) 
-    rhs = parse( expr[3] ) 
-    return Minus( lhs, rhs ) 
- 
-  elseif op_symbol == :iszero 
-    arg = parse( expr[2] ) 
-    return IsZero( arg ) 
- 
-  elseif op_symbol == :ifb 
-    condition = parse( expr[2] ) 
-    true_branch = parse( expr[3] ) 
-    false_branch = parse( expr[4] ) 
-    return IfB( condition, true_branch,​ false_branch ) 
- 
-  elseif op_symbol == :with    # (with x (+ 5 1) (+ x x) ) 
-    sym = expr[2] 
-    binding_expr = parse( expr[3] ) 
-    body = parse( expr[4] ) 
-    return With( sym, binding_expr,​ body ) 
- 
-  elseif op_symbol == :lambda 
-    formal = expr[2] 
-    formal_type = parse_type(expr[4]) 
-    body = parse(expr[5]) 
-    return FunDef( formal, formal_type,​ body ) 
- 
-  elseif op_symbol == :ncons 
-    f = parse(expr[2]) 
-    r = parse(expr[3]) 
-    return NCons( f, r ) 
- 
-  elseif op_symbol == :nisempty 
-    list = parse(expr[2]) 
-    return NIsEmpty( list ) 
- 
-  elseif op_symbol == :nfirst 
-    list = parse(expr[2]) 
-    return NFirst( list ) 
- 
-  elseif op_symbol == :nrest 
-    list = parse(expr[2]) 
-    return NRest( list ) 
- 
-  else 
-    return FunApp( parse(expr[1]),​ parse(expr[2]) ) 
- 
-  end 
-end 
- 
-function parse( expr::Any ) 
-  throw( LispError("​Invalid expression $expr"​) ) 
-end 
- 
-# =================================================== 
- 
-# Parser for type expressions 
- 
-function parse_type( t::Symbol ) 
-  if (t == :number) 
-    return NumType() 
-  elseif (t == :boolean) 
-    return BoolType() 
-  elseif (t == :nlist) 
-    return NListType() 
-  end 
-end 
- 
-function parse_type( t :: Array{Any} ) 
-  return FunType( parse_type(t[1]),​ 
-                  parse_type(t[3])) 
-end 
- 
-function parse_type( expr::Any ) 
-  throw( LispError("​Invalid type $expr"​) ) 
-end 
- 
-# =================================================== 
- 
-# Type checking functions (modeled after the earlier calc) 
- 
-function type_of_expr( ast::AE ) 
-  return type_of_expr( ast, mtTypeEnvironment() ) 
-end 
- 
-function type_of_expr( ae::Num, env::​TypeEnvironment ) 
-  return NumType() 
-end 
- 
-function type_of_expr( ae::​Boolean,​ env::​TypeEnvironment ) 
-  return BoolType() 
-end 
- 
-function type_of_expr( ae::Plus, env::​TypeEnvironment ) 
-  left = type_of_expr( ae.lhs, env ) 
-  right = type_of_expr( ae.rhs, env ) 
-  return type_of_math_expr( left, right ) 
-end 
- 
-function type_of_expr( ae::Minus, env::​TypeEnvironment ) 
-  left = type_of_expr( ae.lhs, env ) 
-  right = type_of_expr( ae.rhs, env ) 
-  return type_of_math_expr( left, right ) 
-end 
- 
-# the rest of your type-checking functions go here... 
- 
-# =================================================== 
- 
-# Helper function for comparing two type values recursively if necessary 
- 
-same_type( t1::​FunType,​ t2::FunType ) = 
-    (same_type( t1.arg_type,​ t2.arg_type ) 
-  && same_type( t1.result_type,​ t2.result_type )) 
- 
-same_type{ T <: TypeVal }( t1::T, t2::T ) = true 
- 
-same_type( t1::​TypeVal,​ t2::TypeVal ) = false 
- 
-# =================================================== 
- 
-# Type judgments (could be folded into type checking functions) 
- 
-function type_of_math_expr( left::​NumType,​ right::​NumType ) 
-  return NumType() 
-end 
- 
-function type_of_math_expr( left::Any, right::Any ) 
-  throw( LispError("​Operands for + or - must be numbers"​) ) 
-end 
- 
-# the rest of your type-judgement functions (if you choose to separate them) go here... 
- 
-# =================================================== 
- 
-# convenience function to make everything easier 
-function type_of_expr( expr::​AbstractString ) 
-  return type_of_expr( parse( Lexer.lex(expr) ) ) 
-end 
- 
-# =================================================== 
- 
-end # module 
-</​file>​ 
cs330_f2016/lab16shell.txt ยท Last modified: 2021/06/30 23:42 (external edit)