基本方針
- ヒープに確保する。
- MIRでリテラル、setarrayelement、getarrayelementみたいな専用命令を作る。
- LLVMみたいにgetelementptrの実装は難しい
- なぜなら、VMでのMOV命令がスタックの位置を直接指す実装だから
 
- ので、VMにも同じように専用命令を生やす
- get/setarrayelementの命令フォーマット
- destination,heap上のarray番号,indexの値を指すレジスタ番号
- ArrayのワードサイズはVMで確保されたヒープ上に書き込まれていて、インデックス*ワードサイズの計算はランタイムに行うということでいいかなあ
 
GCについて
Reference Countにする場合、Dropをどう実装するか
drop_array()、drop_closure()をプリミティブ命令として用意する?
プリミティブな値の配列ならそのまま開放してよし、オブジェクトを含む(配列の配列とか、クロージャの配列)なら再帰的にdropする必要あり
drop命令をどのタイミングで挿入するか mirgenでletの生存期間を調べるしかない bindsでArgumentの区別はされてるから、環境参照してArgument以外を全部dropする、みたいな感じでええのか
<!-- line:30 -->
enum UpvalueKind{<!-- line:31 -->
 Open{base_ptr:u64,offset:u64},<!-- line:32 -->
 Closed(ObjectIdx)<!-- line:33 -->
}<!-- line:34 -->
struct Upvalue{<!-- line:35 -->
	data:UpvalueKind,<!-- line:36 -->
	ty: ObjType,<!-- line:37 -->
}<!-- line:38 -->
<!-- line:39 -->
type SharedUpValue = Rc<RefCell<Upvalue>><!-- line:40 -->
struct Closure{<!-- line:41 -->
 pub fnproto_i: u64,<!-- line:42 -->
 pub base_ptr: u64, //base pointer to current closure, to calculate open upvalue<!-- line:43 -->
 pub is_closed: bool,<!-- line:44 -->
 pub upvalues: Vec<SharedUpValue>,<!-- line:45 -->
 pub state_storage:StateStorage,<!-- line:46 -->
}<!-- line:47 -->
struct Array{<!-- line:48 -->
 pub d_size:TypeSize,<!-- line:49 -->
 pub raw_data: Vec<RawVal>,<!-- line:50 -->
}<!-- line:51 -->
union HeapObject{<!-- line:52 -->
  clousre: Closure,<!-- line:53 -->
  array: Array,<!-- line:54 -->
  primitive: Vec<RawVal>,<!-- line:55 -->
}<!-- line:56 -->
struct RcObject{<!-- line:57 -->
  refcount:u64,<!-- line:58 -->
  data: HeapObject<!-- line:59 -->
}<!-- line:60 -->
type = ObjectStorage=SlotMap<DefaultKey, RcObject>;<!-- line:61 -->
type = ObjectIdx = DefaultKey;<!-- line:62 -->
<!-- line:63 -->
impl Machine{<!-- line:64 -->
...<!-- line:65 -->
  fn drop_closure(&mut self, objectid:ObjectIdx){<!-- line:66 -->
	let obj = self.get_object_mut(objectid);<!-- line:67 -->
	obj.refcount-=1;<!-- line:68 -->
	if obj.refcount==0{<!-- line:69 -->
      let cls = unsafe{ &obj.data.closure };<!-- line:70 -->
      cls.upvalue.iter().for_each(|upv|{<!-- line:71 -->
	      upv<!-- line:72 -->
      })<!-- line:73 -->
      self.object_storage.remove(objectid)<!-- line:74 -->
	}<!-- line:75 -->
  }<!-- line:76 -->
}<!-- line:77 -->
<!-- line:78 -->用途
例えばcatさんに作ってもらったこの辺の再帰を用いたコードがあるとする
fn gen_metalic_rec(times,freq,oscproto){<!-- line:87 -->
  if(times>0){<!-- line:88 -->
    let next = gen_metalic_rec(times-1,freq*1.176,oscproto)<!-- line:89 -->
    let osc = oscproto();<!-- line:90 -->
    | | { osc(freq) + next() }<!-- line:91 -->
  }else{<!-- line:92 -->
    | | 0.0<!-- line:93 -->
  }<!-- line:94 -->
}<!-- line:95 -->
fn gen_metalic(times,freq){<!-- line:96 -->
  let gen = gen_metalic_rec(times,freq,| | square_0);<!-- line:97 -->
  | | gen() / times<!-- line:98 -->
}<!-- line:99 -->
let lowest_freq = 200.0<!-- line:100 -->
let myoscbank = gen_metalic(6,lowest_freq)<!-- line:101 -->こういう組み込み関数を与えて、
extern enumerate_by: (times,init:float,(x:float,acc:float)->float)->[float]<!-- line:107 --><!-- line:111 -->
fn metalic(times,lowest_freq){<!-- line:112 -->
  let freqs =  enumerate_by(times,lowest_freq, |_x,acc| acc*1.167)<!-- line:113 -->
  let res = map(freqs,|f| `square_0(liftf(f)))<!-- line:114 -->
	        |> foldl(_, |x,acc| `{ $x + $acc } )<!-- line:115 -->
  `{$res / liftf(times)}<!-- line:116 -->
}<!-- line:117 -->
fn dsp(){<!-- line:118 -->
  metalic!(6,200)<!-- line:119 -->
}<!-- line:120 -->
<!-- line:121 -->