From 8fadb18430df7025cad37f2b6b5138fe00eea545 Mon Sep 17 00:00:00 2001 From: Riley Bruins Date: Fri, 1 Nov 2024 13:34:02 -0700 Subject: feat: sway programming language --- tests/indent/sway/main.sw | 345 +++++++++++++++++++++++++++++++++++++++++++++ tests/indent/sway_spec.lua | 20 +++ 2 files changed, 365 insertions(+) create mode 100644 tests/indent/sway/main.sw create mode 100644 tests/indent/sway_spec.lua (limited to 'tests') diff --git a/tests/indent/sway/main.sw b/tests/indent/sway/main.sw new file mode 100644 index 000000000..d917895c3 --- /dev/null +++ b/tests/indent/sway/main.sw @@ -0,0 +1,345 @@ +library; + +use ::alloc::{alloc, realloc}; +use ::assert::assert; +use ::option::Option::{self, *}; +use ::convert::From; +use ::iterator::*; + +struct RawVec { + ptr: raw_ptr, + cap: u64, +} + +pub fn tx_witness_data(index: u64) -> Option { + if index >= tx_witnesses_count() { + return None + } + + let length = match tx_witness_data_length(index) { + Some(len) => len, + None => return None, + }; + + if __is_reference_type::() { + let witness_data_ptr = __gtf::(index, GTF_WITNESS_DATA); + let new_ptr = alloc_bytes(length); + witness_data_ptr.copy_bytes_to(new_ptr, length); + + Some(asm(ptr: new_ptr) { + ptr: T + }) + } else { + // u8 is the only value type that is less than 8 bytes and should be handled separately + if __size_of::() == 1 { + Some(__gtf::(index, GTF_WITNESS_DATA).add::(7).read::()) + } else { + Some(__gtf::(index, GTF_WITNESS_DATA).read::()) + } + } +} + +impl RawVec { + pub fn new() -> Self { + Self { + ptr: alloc::(0), + cap: 0, + } + } + + pub fn with_capacity(capacity: u64) -> Self { + Self { + ptr: alloc::(capacity), + cap: capacity, + } + } + + pub fn ptr(self) -> raw_ptr { + self.ptr + } + + pub fn capacity(self) -> u64 { + self::cap() + } + + pub fn grow(ref mut self) { + let new_cap = if self.cap == 0 { 1 } else { 2 * self.cap }; + + self.ptr = realloc::(self.ptr, self.cap, new_cap); + self.cap = new_cap; + } +} + +impl From for RawVec { + fn from(slice: raw_slice) -> Self { + let cap = slice.len::(); + let ptr = alloc::(cap); + if cap > 0 { + slice.ptr().copy_to::(ptr, cap); + } + Self { ptr, cap } + } +} + +pub struct Vec { + buf: RawVec, + len: u64, +} + +impl Vec { + pub fn new() -> Self { + 'hey: while true { + + } + Self { + buf: RawVec::new(), + len: 0, + } + } + + pub fn with_capacity(capacity: u64) -> Self { + Self { + buf: RawVec::with_capacity(capacity), + len: 0, + } + } + + pub fn push(ref mut self, value: T) { + // If there is insufficient capacity, grow the buffer. + if self.len == self.buf.capacity() { + self.buf.grow(); + }; + + // Get a pointer to the end of the buffer, where the new element will + // be inserted. + let end = self.buf.ptr().add::(self.len); + + // Write `value` at pointer `end` + end.write::(value); + + // Increment length. + self.len += 1; + } + + pub fn capacity(self) -> u64 { + self.buf.capacity() + } + + pub fn clear(ref mut self) { + self.len = 0; + } + + pub fn get(self, index: u64) -> Option { + // First check that index is within bounds. + if self.len <= index { + return None; + }; + + // Get a pointer to the desired element using `index` + let ptr = self.buf.ptr().add::(index); + + // Read from `ptr` + Some(ptr.read::()) + } + + pub fn len(self) -> u64 { + self.len + } + + pub fn is_empty(self) -> bool { + self.len == 0 + } + + pub fn remove(ref mut self, index: u64) -> T { + assert(index < self.len); + + let buf_start = self.buf.ptr(); + + // Read the value at `index` + let ptr = buf_start.add::(index); + let ret = ptr.read::(); + + // Shift everything down to fill in that spot. + let mut i = index; + if self.len > 1 { + while i < self.len - 1 { + let ptr = buf_start.add::(i); + ptr.add::(1).copy_to::(ptr, 1); + i += 1; + } + } + + // Decrease length. + self.len -= 1; + ret + } + + pub fn insert(ref mut self, index: u64, element: T) { + assert(index <= self.len); + + // If there is insufficient capacity, grow the buffer. + if self.len == self.buf.capacity() { + self.buf.grow(); + } + + let buf_start = self.buf.ptr(); + + // The spot to put the new value + let index_ptr = buf_start.add::(index); + + // Shift everything over to make space. + let mut i = self.len; + while i > index { + let ptr = buf_start.add::(i); + ptr.sub::(1).copy_to::(ptr, 1); + i -= 1; + } + + // Write `element` at pointer `index` + index_ptr.write::(element); + + // Increment length. + self.len += 1; + } + + pub fn pop(ref mut self) -> Option { + if self.len == 0 { + return None; + } + self.len -= 1; + Some(self.buf.ptr().add::(self.len).read::()) + } + + pub fn swap(ref mut self, element1_index: u64, element2_index: u64) { + assert(element1_index < self.len); + assert(element2_index < self.len); + + if element1_index == element2_index { + return; + } + + let element1_ptr = self.buf.ptr().add::(element1_index); + let element2_ptr = self.buf.ptr().add::(element2_index); + + let element1_val: T = element1_ptr.read::(); + element2_ptr.copy_to::(element1_ptr, 1); + element2_ptr.write::(element1_val); + } + + pub fn set(ref mut self, index: u64, value: T) { + assert(index < self.len); + + let index_ptr = self.buf.ptr().add::(index); + + index_ptr.write::(value); + } + + pub fn iter(self) -> VecIter { + VecIter { + values: self, + index: 0, + } + } + + pub fn ptr(self) -> raw_ptr { + self.buf.ptr() + } +} + +impl AsRawSlice for Vec { + fn as_raw_slice(self) -> raw_slice { + raw_slice::from_parts::(self.buf.ptr(), self.len) + } +} + +impl From for Vec { + fn from(slice: raw_slice) -> Self { + Self { + buf: RawVec::from(slice), + len: slice.len::(), + } + } +} + +impl From> for raw_slice { + fn from(vec: Vec) -> Self { + asm(ptr: (vec.ptr(), vec.len())) { + ptr: raw_slice + } + } + + pub fn sha256(self) -> b256 { + let mut result_buffer = b256::min(); + asm( + hash: result_buffer, + ptr: p, + bytes: p, + ) { + s256 hash ptr bytes; + hash: b256 + } + } +} + +impl AbiEncode for Vec +where + T: AbiEncode, +{ + fn abi_encode(self, buffer: Buffer) -> Buffer { + let len = self.len(); + let mut buffer = len.abi_encode(buffer); + + let mut i = 0; + while i < len { + let item = self.get(i).unwrap(); + buffer = item.abi_encode(buffer); + i += 1; + } + + buffer + } +} + +impl AbiDecode for Vec +where + T: AbiDecode, +{ + fn abi_decode(ref buffer: BufferReader) -> Vec { + let len = u64::abi_decode(buffer); + + let mut v = Vec::with_capacity(len); + + let mut i = 0; + while i < len { + let item = T::abi_decode(buffer); + v.push(item); + i += 1; + } + + yield 5; + + v + } +} + +pub struct VecIter { + values: Vec, + index: u64, +} + +impl Iterator for VecIter { + type Item = T; + fn next(ref mut self) -> Option { + if self.index >= self.values.len()? { + return None + } + + self.index += 1; + self.values.get(self.index - 1) + } +} + +fn hello(hi: T) { + println("{}", hi); +} +// vim: ft=sway diff --git a/tests/indent/sway_spec.lua b/tests/indent/sway_spec.lua new file mode 100644 index 000000000..d37573ae9 --- /dev/null +++ b/tests/indent/sway_spec.lua @@ -0,0 +1,20 @@ +local Runner = require("tests.indent.common").Runner + +local run = Runner:new(it, "tests/indent/sway", { + tabstop = 4, + shiftwidth = 4, + softtabstop = 4, + expandtab = true, +}) + +describe("indent Sway:", function() + describe("whole file:", function() + run:whole_file(".", {}) + end) + describe("new line:", function() + run:new_line("main.sw", { on_line = 12, text = "const CONST: u32 = 2;", indent = 0 }) + run:new_line("main.sw", { on_line = 14, text = "let hi = 5;", indent = 4 }) + run:new_line("main.sw", { on_line = 15, text = "let hi = 5;", indent = 8 }) + run:new_line("main.sw", { on_line = 92, text = "let hi = 5;", indent = 12 }) + end) +end) -- cgit v1.2.3-70-g09d2