Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More libfuncs #12

Closed
wants to merge 15 commits into from
2 changes: 2 additions & 0 deletions src/test_utils.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#![cfg(test)]

use std::{fs, path::Path, sync::Arc};

use cairo_lang_compiler::{
Expand Down
10 changes: 7 additions & 3 deletions src/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ pub enum Value {
U32(u32),
U64(u64),
U8(u8),
Null,
Uninitialized {
ty: ConcreteTypeId,
},
Expand All @@ -80,6 +81,7 @@ impl Value {
CoreTypeConcrete::Uint16(_) => Value::U16(0),
CoreTypeConcrete::Uint128(_) => Value::U128(0),
CoreTypeConcrete::Felt252(_) => Value::Felt(0.into()),
CoreTypeConcrete::Nullable(_) => Value::Null,
x => panic!("type {:?} has no default value implementation", x.info()),
}
}
Expand All @@ -106,7 +108,9 @@ impl Value {
matches!(self, Self::FeltDict { ty, .. } if *ty == info.ty)
}
CoreTypeConcrete::GasBuiltin(_) => matches!(self, Self::U128(_)),
CoreTypeConcrete::NonZero(info) => self.is(registry, &info.ty),
CoreTypeConcrete::NonZero(info) => {
self.is(registry, &info.ty)
}
CoreTypeConcrete::Sint128(_) => matches!(self, Self::I128(_)),
CoreTypeConcrete::Sint32(_) => matches!(self, Self::I32(_)),
CoreTypeConcrete::Sint8(_) => matches!(self, Self::I8(_)),
Expand Down Expand Up @@ -172,8 +176,8 @@ impl Value {
| StarkNetTypeConcrete::StorageBaseAddress(_)
| StarkNetTypeConcrete::StorageAddress(_) => matches!(self, Self::Felt(_)),
StarkNetTypeConcrete::System(_) => matches!(self, Self::Unit),
StarkNetTypeConcrete::Secp256Point(_) => todo!(),
StarkNetTypeConcrete::Sha256StateHandle(_) => todo!(),
StarkNetTypeConcrete::Secp256Point(_) => matches!(self, Self::Struct { .. }),
StarkNetTypeConcrete::Sha256StateHandle(_) => matches!(self, Self::Struct { .. }),
},
};

Expand Down
5 changes: 5 additions & 0 deletions src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::{
use cairo_lang_sierra::{
edit_state,
extensions::{
circuit::CircuitTypeConcrete,
core::{CoreConcreteLibfunc, CoreLibfunc, CoreType, CoreTypeConcrete},
starknet::StarkNetTypeConcrete,
ConcreteType,
Expand Down Expand Up @@ -137,6 +138,10 @@ impl<S: StarknetSyscallHandler> VirtualMachine<S> {
}
CoreTypeConcrete::StarkNet(StarkNetTypeConcrete::System(_)) => Value::Unit,
CoreTypeConcrete::RangeCheck(_)
| CoreTypeConcrete::RangeCheck96(_)
| CoreTypeConcrete::Circuit(
CircuitTypeConcrete::MulMod(_) | CircuitTypeConcrete::AddMod(_),
)
| CoreTypeConcrete::Pedersen(_)
| CoreTypeConcrete::Poseidon(_)
| CoreTypeConcrete::Bitwise(_)
Expand Down
67 changes: 64 additions & 3 deletions src/vm/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use cairo_lang_sierra::{
array::ArrayConcreteLibfunc,
core::{CoreLibfunc, CoreType, CoreTypeConcrete},
lib_func::{SignatureAndTypeConcreteLibfunc, SignatureOnlyConcreteLibfunc},
ConcreteLibfunc,
},
program_registry::ProgramRegistry,
};
Expand All @@ -17,7 +18,7 @@ pub fn eval(
) -> EvalAction {
match selector {
ArrayConcreteLibfunc::New(info) => eval_new(registry, info, args),
ArrayConcreteLibfunc::SpanFromTuple(_) => todo!(),
ArrayConcreteLibfunc::SpanFromTuple(info) => eval_span_from_tuple(registry, info, args),
ArrayConcreteLibfunc::TupleFromSpan(_) => todo!(),
ArrayConcreteLibfunc::Append(info) => eval_append(registry, info, args),
ArrayConcreteLibfunc::PopFront(info) => eval_pop_front(registry, info, args),
Expand All @@ -29,7 +30,9 @@ pub fn eval(
eval_snapshot_pop_front(registry, info, args)
}
ArrayConcreteLibfunc::SnapshotPopBack(info) => eval_snapshot_pop_back(registry, info, args),
ArrayConcreteLibfunc::SnapshotMultiPopFront(_) => todo!(),
ArrayConcreteLibfunc::SnapshotMultiPopFront(info) => {
eval_snapshot_multi_pop_front(registry, info, args)
}
ArrayConcreteLibfunc::SnapshotMultiPopBack(_) => todo!(),
}
}
Expand All @@ -48,7 +51,7 @@ pub fn eval_new(
CoreTypeConcrete::Array(info) => &info.ty,
_ => unreachable!(),
};

//dbg!("ARRAY: {}", &ty);
EvalAction::NormalBranch(
0,
smallvec![Value::Array {
Expand All @@ -58,6 +61,38 @@ pub fn eval_new(
)
}

fn eval_span_from_tuple(
registry: &ProgramRegistry<CoreType, CoreLibfunc>,
info: &SignatureAndTypeConcreteLibfunc,
args: Vec<Value>,
) -> EvalAction {
let [Value::Struct(data)]: [Value; 1] = args.try_into().unwrap() else {
panic!()
};

let type_info = registry
.get_type(&info.branch_signatures()[0].vars[0].ty)
.unwrap();
let ty = match type_info {
CoreTypeConcrete::Snapshot(info) => {
let type_info = registry.get_type(&info.ty).unwrap();
match type_info {
CoreTypeConcrete::Array(info) => &info.ty,
_ => unreachable!(),
}
}
_ => unreachable!(),
};

EvalAction::NormalBranch(
0,
smallvec![Value::Array {
ty: ty.clone(),
data
}],
)
}

pub fn eval_append(
registry: &ProgramRegistry<CoreType, CoreLibfunc>,
info: &SignatureAndTypeConcreteLibfunc,
Expand Down Expand Up @@ -185,3 +220,29 @@ pub fn eval_snapshot_pop_back(
EvalAction::NormalBranch(1, smallvec![Value::Array { data, ty }])
}
}

fn eval_snapshot_multi_pop_front(
registry: &ProgramRegistry<CoreType, CoreLibfunc>,
info: &cairo_lang_sierra::extensions::array::ConcreteMultiPopLibfunc,
args: Vec<Value>,
) -> EvalAction {
let [rangecheck, Value::Array { mut data, ty }]: [Value; 2] = args.try_into().unwrap() else {
panic!()
};

let CoreTypeConcrete::Struct(popped_cty) = registry.get_type(&info.popped_ty).unwrap() else {
panic!()
};

if data.len() >= popped_cty.members.len() {
let new_data = data.split_off(popped_cty.members.len());
let value = Value::Struct(data);
assert!(value.is(registry, &info.popped_ty));
EvalAction::NormalBranch(
0,
smallvec![rangecheck, Value::Array { data: new_data, ty }, value],
)
} else {
EvalAction::NormalBranch(1, smallvec![rangecheck, Value::Array { data, ty }])
}
}
4 changes: 4 additions & 0 deletions src/vm/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ pub fn eval_upcast(
CoreTypeConcrete::Uint32(_) => Value::U32(value.try_into().unwrap()),
CoreTypeConcrete::Uint64(_) => Value::U64(value.try_into().unwrap()),
CoreTypeConcrete::Uint128(_) => Value::U128(value.try_into().unwrap()),
CoreTypeConcrete::Felt252(_) => Value::Felt(value.try_into().unwrap()),
CoreTypeConcrete::Sint16(_) => todo!("Sint16"),
CoreTypeConcrete::Sint64(_) => todo!("Sint64"),
CoreTypeConcrete::BoundedInt(_) => todo!("BoundedInt"),
_ => todo!(),
}],
)
Expand Down
183 changes: 104 additions & 79 deletions src/vm/const.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ use super::EvalAction;
use crate::Value;
use cairo_lang_sierra::{
extensions::{
const_type::{ConstAsImmediateConcreteLibfunc, ConstConcreteLibfunc},
const_type::{
ConstAsBoxConcreteLibfunc, ConstAsImmediateConcreteLibfunc, ConstConcreteLibfunc,
},
core::{CoreLibfunc, CoreType, CoreTypeConcrete},
},
ids::ConcreteTypeId,
Expand All @@ -17,7 +19,7 @@ pub fn eval(
args: Vec<Value>,
) -> EvalAction {
match selector {
ConstConcreteLibfunc::AsBox(_) => todo!(),
ConstConcreteLibfunc::AsBox(info) => eval_as_box(registry, info, args),
ConstConcreteLibfunc::AsImmediate(info) => eval_as_immediate(registry, info, args),
}
}
Expand All @@ -29,94 +31,117 @@ pub fn eval_as_immediate(
) -> EvalAction {
let [] = args.try_into().unwrap();

fn inner(
registry: &ProgramRegistry<CoreType, CoreLibfunc>,
type_id: &ConcreteTypeId,
inner_data: &[GenericArg],
) -> Value {
match registry.get_type(type_id).unwrap() {
CoreTypeConcrete::BoundedInt(info) => match inner_data {
[GenericArg::Type(type_id)] => match registry.get_type(type_id).unwrap() {
CoreTypeConcrete::Const(info) => {
inner(registry, &info.inner_ty, &info.inner_data)
}
_ => unreachable!(),
},
[GenericArg::Value(value)] => {
assert!(value >= &info.range.lower && value < &info.range.upper);
Value::BoundedInt {
range: info.range.lower.clone()..info.range.upper.clone(),
value: value.clone(),
}
}
_ => unreachable!(),
},
CoreTypeConcrete::Felt252(_) => match inner_data {
[GenericArg::Value(value)] => Value::Felt(value.into()),
_ => unreachable!(),
},
CoreTypeConcrete::NonZero(info) => inner(registry, &info.ty, inner_data),
CoreTypeConcrete::Sint128(_) => match inner_data {
[GenericArg::Value(value)] => Value::I128(value.try_into().unwrap()),
_ => unreachable!(),
},
CoreTypeConcrete::Sint32(_) => match inner_data {
[GenericArg::Value(value)] => Value::I32(value.try_into().unwrap()),
_ => unreachable!(),
},
CoreTypeConcrete::Sint8(_) => match inner_data {
[GenericArg::Value(value)] => Value::I8(value.try_into().unwrap()),
_ => unreachable!(),
},
CoreTypeConcrete::Uint64(_) => match inner_data {
[GenericArg::Value(value)] => Value::U64(value.try_into().unwrap()),
_ => unreachable!(),
},
CoreTypeConcrete::Uint32(_) => match inner_data {
[GenericArg::Value(value)] => Value::U32(value.try_into().unwrap()),
let const_ty = match registry.get_type(&info.const_type).unwrap() {
CoreTypeConcrete::Const(x) => x,
_ => unreachable!(),
};
EvalAction::NormalBranch(
0,
smallvec![inner(registry, &const_ty.inner_ty, &const_ty.inner_data)],
)
}

pub fn eval_as_box(
registry: &ProgramRegistry<CoreType, CoreLibfunc>,
info: &ConstAsBoxConcreteLibfunc,
args: Vec<Value>,
) -> EvalAction {
let [] = args.try_into().unwrap();

let const_ty = match registry.get_type(&info.const_type).unwrap() {
CoreTypeConcrete::Const(x) => x,
_ => unreachable!(),
};
EvalAction::NormalBranch(
0,
smallvec![inner(registry, &const_ty.inner_ty, &const_ty.inner_data)],
)
}

fn inner(
registry: &ProgramRegistry<CoreType, CoreLibfunc>,
type_id: &ConcreteTypeId,
inner_data: &[GenericArg],
) -> Value {
match registry.get_type(type_id).unwrap() {
CoreTypeConcrete::BoundedInt(info) => match inner_data {
[GenericArg::Type(type_id)] => match registry.get_type(type_id).unwrap() {
CoreTypeConcrete::Const(info) => inner(registry, &info.inner_ty, &info.inner_data),
_ => unreachable!(),
},
CoreTypeConcrete::Uint8(_) => match inner_data {
[GenericArg::Value(value)] => Value::U8(value.try_into().unwrap()),
[GenericArg::Value(value)] => {
assert!(value >= &info.range.lower && value < &info.range.upper);
Value::BoundedInt {
range: info.range.lower.clone()..info.range.upper.clone(),
value: value.clone(),
}
}
_ => unreachable!(),
},
CoreTypeConcrete::Felt252(_) => match inner_data {
[GenericArg::Value(value)] => Value::Felt(value.into()),
_ => unreachable!(),
},
CoreTypeConcrete::NonZero(info) => inner(registry, &info.ty, inner_data),
CoreTypeConcrete::Sint128(_) => match inner_data {
[GenericArg::Value(value)] => Value::I128(value.try_into().unwrap()),
_ => unreachable!(),
},
CoreTypeConcrete::Sint32(_) => match inner_data {
[GenericArg::Value(value)] => Value::I32(value.try_into().unwrap()),
_ => unreachable!(),
},
CoreTypeConcrete::Sint8(_) => match inner_data {
[GenericArg::Value(value)] => Value::I8(value.try_into().unwrap()),
_ => unreachable!(),
},
CoreTypeConcrete::Uint64(_) => match inner_data {
[GenericArg::Value(value)] => Value::U64(value.try_into().unwrap()),
_ => unreachable!(),
},
CoreTypeConcrete::Uint32(_) => match inner_data {
[GenericArg::Value(value)] => Value::U32(value.try_into().unwrap()),
[GenericArg::Type(type_id)] => match registry.get_type(type_id).unwrap() {
CoreTypeConcrete::Const(info) => inner(registry, &info.inner_ty, &info.inner_data),
_ => unreachable!(),
},
CoreTypeConcrete::Uint128(_) => match inner_data {
[GenericArg::Value(value)] => Value::U128(value.try_into().unwrap()),
_ => unreachable!(),
},
CoreTypeConcrete::Uint8(_) => match inner_data {
[GenericArg::Value(value)] => Value::U8(value.try_into().unwrap()),
_ => unreachable!(),
},
CoreTypeConcrete::Uint128(_) => match inner_data {
[GenericArg::Value(value)] => Value::U128(value.try_into().unwrap()),
[GenericArg::Type(type_id)] => match registry.get_type(type_id).unwrap() {
CoreTypeConcrete::Const(info) => inner(registry, &info.inner_ty, &info.inner_data),
_ => unreachable!(),
},
CoreTypeConcrete::Struct(_) => {
let mut fields = Vec::new();
_ => unreachable!(),
},
CoreTypeConcrete::Struct(_) => {
let mut fields = Vec::new();

for field in inner_data {
match field {
GenericArg::Type(const_field_ty) => {
let field_type = registry.get_type(const_field_ty).unwrap();
for field in inner_data {
match field {
GenericArg::Type(const_field_ty) => {
let field_type = registry.get_type(const_field_ty).unwrap();

match &field_type {
CoreTypeConcrete::Const(const_ty) => {
let field_value =
inner(registry, &const_ty.inner_ty, &const_ty.inner_data);
fields.push(field_value);
}
_ => unreachable!(),
};
}
_ => unreachable!(),
match &field_type {
CoreTypeConcrete::Const(const_ty) => {
let field_value =
inner(registry, &const_ty.inner_ty, &const_ty.inner_data);
fields.push(field_value);
}
_ => unreachable!(),
};
}
_ => unreachable!(),
}

Value::Struct(fields)
}
_ => todo!("{}", type_id),

Value::Struct(fields)
}
_ => todo!("{}", type_id),
}

let const_ty = match registry.get_type(&info.const_type).unwrap() {
CoreTypeConcrete::Const(x) => x,
_ => unreachable!(),
};
EvalAction::NormalBranch(
0,
smallvec![inner(registry, &const_ty.inner_ty, &const_ty.inner_data)],
)
}
Loading