Skip to content

Commit 8d4bff9

Browse files
committed
Added return to tweaked machine - WIP
1 parent a5ae6d8 commit 8d4bff9

File tree

1 file changed

+156
-1
lines changed

1 file changed

+156
-1
lines changed

lib/uplc/tweaked_machine.ak

Lines changed: 156 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ pub type Context {
2222
FrameAwaitFunTerm(Env, TermHash, ContextHash)
2323
FrameAwaitFunValue(Value, ContextHash)
2424
FrameForce(ContextHash)
25-
FrameConstr(Env, Int, List<TermHash>, List<Value>, ContextHash)
25+
FrameConstr(Env, Int, List<TermHash>, List<ValueHash>, ContextHash)
2626
FrameCases(Env, List<TermHash>, ContextHash)
2727
NoFrame
2828
}
@@ -52,6 +52,7 @@ pub type MachineState {
5252
// ReturnAwaitValue(Context, ValueHash)
5353
Done(TermHash)
5454
IteratingEnv(Context, Env, Int)
55+
// IteratingFields(Context, List<ValueHash>, Env, TermHash)
5556
ErrorState(ByteArray)
5657
}
5758

@@ -134,3 +135,157 @@ pub fn compute(
134135
_ -> fail
135136
}
136137
}
138+
139+
pub fn return(ctx: Context, value_hash: ValueHash, value: Value, inner_context: Option<Context>) -> MachineState {
140+
expect value_hash == ( value |> builtin.serialise_data |> hashing_algo )
141+
142+
when ctx is {
143+
FrameAwaitArg(function, ctx_hash) ->
144+
apply_eval(ctx_hash, function, value_hash, inner_context)
145+
146+
FrameAwaitFunTerm(arg_env, arg_hash, ctx_hash) -> {
147+
let frame = FrameAwaitArg(value, ctx_hash)
148+
149+
Compute(frame, arg_env, arg_hash)
150+
}
151+
152+
FrameAwaitFunValue(arg, ctx_hash) -> {
153+
let arg_hash = ( arg |> builtin.serialise_data |> hashing_algo )
154+
apply_eval(ctx_hash, value, arg_hash, inner_context)
155+
}
156+
157+
FrameForce(ctx_hash) ->
158+
force_eval(ctx_hash, value_hash, value, inner_context)
159+
160+
NoFrame ->
161+
Done(discharge_value(value) |> builtin.serialise_data |> hashing_algo)
162+
163+
FrameConstr(env, tag, fields, eval_fields, ctx_hash) -> {
164+
// FrameConstr(Env, Int, List<TermHash>, List<Value>, ContextHash)
165+
let done = [value_hash, ..eval_fields]
166+
167+
when fields is {
168+
[] -> {
169+
expect Some(inner_context) = inner_context
170+
let constr_value = VConstr { tag, fields: done }
171+
let constr_hash = constr_value |> builtin.serialise_data |> hashing_algo
172+
Return(inner_context, constr_hash)
173+
}
174+
[next_hash, ..rest] ->
175+
Compute(
176+
FrameConstr(env, tag, rest, done, ctx_hash),
177+
env,
178+
next_hash
179+
)
180+
}
181+
}
182+
183+
FrameCases(env, cs, ctx_hash) ->
184+
when value is {
185+
VConstr { tag, fields } -> {
186+
let branch_hash = cs |> list_at(tag)
187+
188+
// Use the new iterative approach instead of recursive transfer_fields
189+
expect Some(ctx) = inner_context
190+
expect ctx_hash == ( ctx |> builtin.serialise_data |> hashing_algo )
191+
// Can we use a Return instead of IteratingFields?
192+
if builtin.null_list(fields) {
193+
// No fields to transfer
194+
Compute(ctx, env, branch_hash)
195+
} else {
196+
todo
197+
}
198+
}
199+
_ -> ErrorState("Not a constr")
200+
}
201+
}
202+
}
203+
204+
fn force_eval(ctx_hash: ContextHash, value_hash: ValueHash, value: Value, ctx: Option<Context>) -> MachineState {
205+
expect Some(ctx) = ctx
206+
expect ctx_hash == ( ctx |> builtin.serialise_data |> hashing_algo )
207+
expect value_hash == ( ctx |> builtin.serialise_data |> hashing_algo )
208+
when value is {
209+
VDelay(body_hash, env) ->
210+
Compute(ctx, env, body_hash)
211+
212+
VBuiltin { fun, force_count, args_count, args } ->
213+
if force_count > 0 {
214+
let new_value =
215+
VBuiltin {
216+
fun,
217+
force_count: force_count - 1,
218+
args_count,
219+
args
220+
}
221+
let new_hash = new_value |> builtin.serialise_data |> hashing_algo
222+
223+
Return(ctx, new_hash)
224+
} else {
225+
ErrorState("builtin term argument expected")
226+
}
227+
228+
_ -> ErrorState("nonpolymorphic instantiation")
229+
}
230+
}
231+
232+
fn apply_eval(ctx_hash: ContextHash, function: Value, argument: ValueHash, ctx: Option<Context>) -> MachineState {
233+
expect Some(ctx) = ctx
234+
expect ctx_hash == ( ctx |> builtin.serialise_data |> hashing_algo )
235+
when function is {
236+
VLambda { body: body_hash, env } -> {
237+
let new_env = Env {
238+
value: argument,
239+
next: env |> builtin.serialise_data |> hashing_algo,
240+
}
241+
242+
Compute(ctx, new_env, body_hash)
243+
}
244+
245+
VBuiltin { fun, force_count, args_count, args } ->
246+
if force_count == 0 {
247+
let result = eval_builtin(fun, args_count, args, argument)
248+
Return(ctx, result)
249+
} else {
250+
ErrorState("Unexpected Builtin Term Argument")
251+
}
252+
253+
_ -> ErrorState("Not a function")
254+
}
255+
}
256+
257+
fn eval_builtin(
258+
fun: Int,
259+
args_count: Int,
260+
args: List<ValueHash>,
261+
next_arg: ValueHash,
262+
) -> ValueHash {
263+
if args_count == 0 {
264+
fail @"Impossible"
265+
} else if args_count == 1 {
266+
// TODO: Implement call_builtin for the tweaked machine
267+
// This is a placeholder - actual implementation would need to handle builtins
268+
fail @"call_builtin not implemented"
269+
} else {
270+
VBuiltin {
271+
fun,
272+
force_count: 0,
273+
args_count: args_count - 1,
274+
args: [next_arg, ..args],
275+
} |> builtin.serialise_data |> hashing_algo
276+
}
277+
}
278+
279+
fn list_at(list: List<a>, index: Int) -> a {
280+
if index == 0 {
281+
list |> builtin.head_list
282+
} else {
283+
list |> builtin.tail_list |> list_at(index - 1)
284+
}
285+
}
286+
287+
fn discharge_value(value: Value) -> Term {
288+
// This is a placeholder - actual implementation would need to convert Value to Term
289+
// Similar to the implementation in machine.ak but adapted for the tweaked machine
290+
fail @"discharge_value not implemented"
291+
}

0 commit comments

Comments
 (0)