aboutsummaryrefslogtreecommitdiff
path: root/snug-clean/src/Snug/Compile.icl
blob: c354950c5c68e5af483d8aade9c60ac973bc7f36 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
implementation module Snug.Compile

import StdEnv

import Control.Monad
import Data.Func
import Data.List
import qualified Data.Map
from Data.Map import :: Map

import MIPS.MIPS32
import Snug.Compile.ABI
import Snug.Compile.Simulate
import Snug.Syntax

:: Locals :== Map SymbolIdent MemoryLocation

:: MemoryLocation
	= InRegister !Register
	| Indirect !Register !Offset

instance == (Namespaced id) | == id
where
	(==) x y = x.id == y.id && x.ns == y.ns

instance < (Namespaced id) | < id
where
	(<) x y
		| x.id < y.id = True
		| x.id > y.id = False
		| otherwise = x.ns < y.ns

compile :: !Namespace ![Definition] -> [Line]
compile ns defs =
	concatMap (compileDefinition ns globals) defs
where
	globals =
		{ constructors = 'Data.Map'.fromList
			[ ({ns="", id="INT"}, ConstructorDef "INT" [])
			]
		, functions = 'Data.Map'.newMap
		}

compileDefinition :: !Namespace !Globals !Definition -> [Line]
compileDefinition _ _ (TypeDef _ _) =
	[]
compileDefinition ns globals (DataDef _ _ constructors) =
	[ StartSection "data"
	: concatMap (compileConstructor ns globals) constructors
	]
compileDefinition ns globals (FunDef id args ret expr) =
	[ StartSection "text"
	// TODO: Ideally we would use the following here:
	//, Align 1
	//, RawByte (sum [2^i \\ i <- [0..] & _ <- args]) // all strict for now, TODO change
	//, RawByte (length args) // arity
	// But since SPIM does not allow .byte in the text section, we use:
	, Align 2
	, RawWord
		(sum [2^i \\ i <- [0..] & _ <- args] bitor // all strict for now, TODO change
		(length args << 8)) // arity
	// instead... (end modification)
	, Label (functionLabel ns NodeEntry id)
	: map Instr (compileExpr ns globals locals expr)
	]
where
	locals = 'Data.Map'.fromList
		[ (id, Indirect FrontEvalPtr (offset*4))
		\\ (id,_) <- args
		& offset <- [1..]
		]

compileConstructor :: !Namespace !Globals !ConstructorDef -> [Line]
compileConstructor ns _ (ConstructorDef id args) =
	[ Align 1
	, Label (constructorLabel ns id)
	, RawByte (length args) // pointer arity
	, RawByte 0 // basic value arity
	, RawByte 0 // number of arguments still to be curried in
	]

compileExpr :: !Namespace !Globals !Locals !Expression -> [Instruction]
compileExpr ns globals locals expr = simulate $
	simulator ns globals locals expr >>|
	indirectAndEval

simulator :: !Namespace !Globals !Locals !Expression -> Simulator ()
simulator _ _ _ (BasicValue bv) =
	pushBasicValue bv >>|
	buildCons (constructorLabel "" (label bv)) 1
where
	label (BVInt _) = "INT"
	label (BVChar _) = "CHAR"
simulator _ _ _ _ = // TODO
	pushBasicValue (BVInt 0) >>|
	buildCons (constructorLabel "" "INT") 1
//	| Symbol !SymbolIdent
//	| Constructor !ConstructorIdent
//	| Case !Expression ![CaseAlternative]
//	| ExpApp !Expression !Expression