Skip to content

Commit

Permalink
Merge pull request #13 from lambdaclass/libs
Browse files Browse the repository at this point in the history
Implement libfuncs
  • Loading branch information
edg-l authored Oct 16, 2024
2 parents 578c7fd + 23f439e commit 18f9e75
Show file tree
Hide file tree
Showing 9 changed files with 253 additions and 91 deletions.
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
2 changes: 1 addition & 1 deletion src/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ impl Value {
| StarkNetTypeConcrete::StorageAddress(_) => matches!(self, Self::Felt(_)),
StarkNetTypeConcrete::System(_) => matches!(self, Self::Unit),
StarkNetTypeConcrete::Secp256Point(_) => todo!(),
StarkNetTypeConcrete::Sha256StateHandle(_) => todo!(),
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
30 changes: 29 additions & 1 deletion src/vm/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,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 Down Expand Up @@ -185,3 +187,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: 102 additions & 81 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,113 @@ 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()),
_ => unreachable!(),
},
CoreTypeConcrete::Uint8(_) => match inner_data {
[GenericArg::Value(value)] => Value::U8(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::Uint128(_) => match inner_data {
[GenericArg::Value(value)] => Value::U128(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::Struct(_) => {
let mut fields = Vec::new();
_ => 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()),
_ => 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)],
)
}
6 changes: 2 additions & 4 deletions src/vm/int128.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use std::u128;

use cairo_lang_sierra::{
extensions::{
core::{CoreLibfunc, CoreType},
Expand All @@ -22,12 +20,12 @@ pub fn eval(
args: Vec<Value>,
) -> EvalAction {
match selector {
Sint128Concrete::Const(info) => todo!("1"),
Sint128Concrete::Const(_) => todo!("int128 const"),
Sint128Concrete::Operation(info) => eval_operation(registry, info, args),
Sint128Concrete::Equal(info) => eval_equal(registry, info, args),
Sint128Concrete::ToFelt252(info) => eval_to_felt(registry, info, args),
Sint128Concrete::FromFelt252(info) => eval_from_felt(registry, info, args),
Sint128Concrete::IsZero(info) => todo!("6"),
Sint128Concrete::IsZero(_) => todo!("int128 is_zero"),
Sint128Concrete::Diff(info) => eval_diff(registry, info, args),
}
}
Expand Down
Loading

0 comments on commit 18f9e75

Please sign in to comment.