From ca9cc763d918d0b6fdfdc7ab55228676283c6393 Mon Sep 17 00:00:00 2001 From: "hyunghwan.chung" Date: Sat, 16 Jun 2018 16:45:17 +0000 Subject: [PATCH] fixed a compiler bug in compile_expression_primary. before the fix, the compiler could treat an undotted identifier as dotted. changed a few primitive function names in sck.c wrote some methods for ByteStream --- moo/kernel/Http.moo | 18 +++---- moo/kernel/Socket.moo | 60 ++++++++++++----------- moo/kernel/Stream.moo | 110 ++++++++++++++++++++++++++++++++++++++---- moo/lib/comp.c | 2 +- moo/mod/sck.c | 8 +-- 5 files changed, 145 insertions(+), 53 deletions(-) diff --git a/moo/kernel/Http.moo b/moo/kernel/Http.moo index a6042fd..ff166d5 100644 --- a/moo/kernel/Http.moo +++ b/moo/kernel/Http.moo @@ -128,9 +128,9 @@ class HttpSocket(SyncSocket) 'IM RUNNING SERVICE...............' dump. (* - self readBytes: buf. + self readBytesInto: buf. buf dump. - self readBytes: buf. + self readBytesInto: buf. buf dump. *) @@ -317,7 +317,7 @@ class MyObject(Object) | nbytes | while (true) { - nbytes := csck readBytes: buf. + nbytes := csck readBytesInto: buf. if (nbytes <= 0) { if (nbytes == 0) { csck close }. @@ -326,11 +326,11 @@ class MyObject(Object) }. buf dump. - csck writeBytes: buf offset: 0 length: nbytes. + csck writeBytesFrom: buf offset: 0 length: nbytes. }. ]. clisck onEvent: #data_out do: [ :csck | - ##csck writeBytes: #[ $a, $b, C'\n' ]. + ##csck writeBytesFrom: #[ $a, $b, C'\n' ]. ]. clisck onEvent: #closed do: [ :csck | 'Socket CLOSED....' dump. @@ -353,8 +353,8 @@ class MyObject(Object) s onEvent: #connected do: [ :sck :state | if (state) { - s writeBytes: #[ $a, $b, $c ]. - s writeBytes: #[ $d, $e, $f ]. + s writeBytesFrom: #[ $a, $b, $c ]. + s writeBytesFrom: #[ $d, $e, $f ]. } else { @@ -366,7 +366,7 @@ class MyObject(Object) | nbytes | while (true) { - nbytes := sck readBytes: buf. + nbytes := sck readBytesInto: buf. if (nbytes <= 0) { if (nbytes == 0) { sck close }. @@ -377,7 +377,7 @@ class MyObject(Object) }. ]. s onEvent: #data_out do: [ :sck | - if (count < 10) { sck writeBytes: #[ $a, $b, C'\n' ]. count := count + 1. }. + if (count < 10) { sck writeBytesFrom: #[ $a, $b, C'\n' ]. count := count + 1. }. ]. s connect: (SocketAddress fromString: '127.0.0.1:9999'). diff --git a/moo/kernel/Socket.moo b/moo/kernel/Socket.moo index a401dbe..5d9fc5d 100644 --- a/moo/kernel/Socket.moo +++ b/moo/kernel/Socket.moo @@ -243,18 +243,18 @@ class Socket(Object) from 'sck' method(#primitive) _connect: addr. method(#primitive) _socketError. - method(#primitive) _readBytes: bytes. - method(#primitive) _readBytes: bytes offset: offset length: length. - method(#primitive) _writeBytes: bytes. - method(#primitive) _writeBytes: bytes offset: offset length: length. + method(#primitive) _readBytesInto: bytes. + method(#primitive) _readBytesInto: bytes offset: offset length: length. + method(#primitive) _writeBytesFrom: bytes. + method(#primitive) _writeBytesFrom: bytes offset: offset length: length. method(#class) new { self messageProhibited: #new } method(#class) new: size { self messageProhibited: #new: } - method(#class) __with: handle + method(#class) __with_handle: handle { ###self addToBeFinalized. - ^(self basicNew initialize) __open(handle) + ^(super new) __open(handle) } method(#class) family: family type: type @@ -263,7 +263,7 @@ class Socket(Object) from 'sck' ## new is prohibited. so use _basicNew with initialize. ##^(self new) open(family, type, 0) - ^(self basicNew initialize) open(family, type, 0) + ^(super new) open(family, type, 0) } method close @@ -305,10 +305,11 @@ class SyncSocket(Socket) method(#class) new { self messageProhibited: #new } method(#class) new: size { self messageProhibited: #new: } - method(#class) __with: handle +(* + method(#class) __with_handle: handle { ###self addToBeFinalized. - ^(self basicNew initialize) __open(handle) + ^(super new) __open(handle) } method(#class) family: family type: type @@ -317,8 +318,9 @@ class SyncSocket(Socket) ## new is prohibited. so use _basicNew with initialize. ##^(self new) open(family, type, 0) - ^(self basicNew initialize) open(family, type, 0) + ^(super new) open(family, type, 0) } +*) method initialize { @@ -386,45 +388,45 @@ class SyncSocket(Socket) }. } - method readBytes: bytes + method readBytesInto: bytes { | n | while (true) { - n := super _readBytes: bytes. + n := super _readBytesInto: bytes. if (n >= 0) { ^n }. self __wait_for_input. } } - method readBytes: bytes offset: offset length: length + method readBytesInto: bytes offset: offset length: length { | n | while (true) { - n := super _readBytes: bytes offset: offset length: length. + n := super _readBytesInto: bytes offset: offset length: length. if (n >= 0) { ^n }. self __wait_for_input. } } - method writeBytes: bytes + method writeBytesFrom: bytes { | n | while (true) { - n := super _writeBytes: bytes. + n := super _writeBytesFrom: bytes. if (n >= 0) { ^n }. self __wait_for_output. } } - method writeBytes: bytes offset: offset length: length + method writeBytesFrom: bytes offset: offset length: length { | n | while (true) { - n := super _writeBytes: bytes offset: offset length: length. + n := super _writeBytesFrom: bytes offset: offset length: length. if (n >= 0) { ^n }. self __wait_for_output. } @@ -467,7 +469,7 @@ class AsyncSocket(Socket) while (rem > 0) { - nbytes := self _writeBytes: self.pending_bytes offset: pos length: rem. + nbytes := self _writeBytesFrom: self.pending_bytes offset: pos length: rem. if (nbytes <= -1) { break }. pos := pos + nbytes. rem := rem - nbytes. @@ -529,17 +531,17 @@ class AsyncSocket(Socket) thisProcess addAsyncSemaphore: self.outdonesem. } - method readBytes: bytes + method readBytesInto: bytes { - ^super _readBytes: bytes. + ^super _readBytesInto: bytes. } - method readBytes: bytes offset: offset length: length + method readBytesInto: bytes offset: offset length: length { - ^super _readBytes: bytes offset: offset length: length. + ^super _readBytesInto: bytes offset: offset length: length. } - method writeBytes: bytes offset: offset length: length + method writeBytesFrom: bytes offset: offset length: length { | n pos rem | @@ -557,7 +559,7 @@ class AsyncSocket(Socket) while (rem > 0) { - n := self _writeBytes: bytes offset: pos length: rem. + n := self _writeBytesFrom: bytes offset: pos length: rem. if (n <= -1) { break }. rem := rem - n. pos := pos + n. @@ -577,9 +579,9 @@ class AsyncSocket(Socket) self.outreadysem signalOnOutput: self.handle. } - method writeBytes: bytes + method writeBytesFrom: bytes { - ^self writeBytes: bytes offset: 0 length: (bytes size) + ^self writeBytesFrom: bytes offset: 0 length: (bytes size) } ##method onSocketClosed @@ -674,7 +676,7 @@ class AsyncServerSocket(AsyncSocket) ##if (fd >= 0) if (fd notNil) { - clisck := (self acceptedSocketClass) __with: fd. + clisck := (self acceptedSocketClass) __with_handle: fd. clisck beWatched. self onSocketAccepted: clisck from: cliaddr. }. @@ -743,7 +745,7 @@ class ListenerSocket(Socket) ##if (fd >= 0) if (fd notNil) { - clisck := (self acceptedSocketClass) __with: fd. + clisck := (self acceptedSocketClass) __with_handle: fd. sg addSemaphore: self.inreadysem. self.inreadysem signalOnInput: self.handle. diff --git a/moo/kernel/Stream.moo b/moo/kernel/Stream.moo index 2a3aa42..bedab57 100644 --- a/moo/kernel/Stream.moo +++ b/moo/kernel/Stream.moo @@ -129,8 +129,8 @@ class ExternalStream(ReadWriteStream) ## mimic java's interface... interface ByteStreamable { - readBytes: - writeBytes: + readBytesInto: + writeBytesFrom: } *) @@ -173,7 +173,7 @@ difficulty: how to ensure that the class implements the defined interface? Let me think about it.. *) -class ByteStream(Object) ### [ByteStreamable, ByteXXX] +class ByteStreamAdapter(Object) ### [ByteStreamable, ByteXXX] { var bsobj. var inbuf. @@ -181,6 +181,10 @@ class ByteStream(Object) ### [ByteStreamable, ByteXXX] var inlen. var indown. + var outbuf. + var outlen. + var outdown. + method(#class) new { self messageProhibited: #new. @@ -191,14 +195,19 @@ class ByteStream(Object) ### [ByteStreamable, ByteXXX] self messageProhibited: #new:. } - method initialize + method initialize { super initialize. self.bsobj := nil. + self.inbuf := ByteArray new: 1024. self.inpos := 0. self.inlen := 0. self.indown := false. + + self.outbuf := ByteArray new: 1024. + self.outlen := 0. + self.outdown := false. } method(#class) on: bsobj @@ -214,7 +223,7 @@ class ByteStream(Object) ### [ByteStreamable, ByteXXX] method __fill_inbuf { | v | - v := self.bsobj readBytes: self.inbuf. + v := self.bsobj readBytesInto: self.inbuf. ## if the streamable object is not blocking, it may return an ## error object when data is not ready. if (v isError) { ^v }. @@ -238,7 +247,7 @@ class ByteStream(Object) ### [ByteStreamable, ByteXXX] if (self.inpos >= self.inlen) { v := self __fill_inbuf. - if (v isError) { ^v }. + if (v isError) { ^v }. ## TODO: change error handling if (v <= 0) { ^nil }. ####if (self.inpos >= self.inlen) { ^nil }. }. @@ -251,7 +260,7 @@ class ByteStream(Object) ### [ByteStreamable, ByteXXX] method next: count into: byte_array startingAt: pos { ## return the count bytes - | taken avail needed v | + | taken avail needed v incapa | if (self.indown) { ^0 }. @@ -260,19 +269,33 @@ class ByteStream(Object) ### [ByteStreamable, ByteXXX] ## if the parameters cannot meet this assumption, you will get ## into various system exceptions. needed := count. + incapa := self.inbuf size. while (needed > 0) { avail := self.inlen - self.inpos. if (avail <= 0) { - v := self __fill_inbuf. - if (v isError or v <= 0) { break }. ## <<< TODO: change the error handling + if (needed >= incapa) + { + ## don't rely on the internal buffer if the number of bytes + ## needed are equal to or greater than the capacity of the + ## buffer. + v := self.bsobj readBytesInto: byte_array offset: pos length: needed. + if (v isError or v <= 0) { break }. ## <<< TODO: change the error handling + pos := pos + v. + needed := needed - v. + continue. + } + else + { + v := self __fill_inbuf. + if (v isError or v <= 0) { break }. ## <<< TODO: change the error handling + }. }. taken := if (avail <= needed) { avail } else { needed }. byte_array replaceFrom: pos count: taken with: self.inbuf startingAt: self.inpos. - self.inpos := self.inpos + taken. pos := pos + taken. needed := needed - taken. @@ -281,5 +304,72 @@ class ByteStream(Object) ### [ByteStreamable, ByteXXX] ^count - needed. } + method nextPut: count from: byte_array startingAt: pos + { + | consumed free rem outcapa | + + if (self.outdown) { ^0 }. + + rem := count. + outcapa := self.outbuf size. + + while (rem > 0) + { + free := outcapa - self.outlen. + if (free <= 0) + { + self flush. ## TODO: error handling... + }. + + if (self.outlen <= 0 and rem >= outcapa) + { + consumed := self.bsobj writeBytesFrom: byte_array offset: pos length: rem. + if (consumed <= 0) { break }. ## TODO: error handling. also handle exceptions + } + else + { + consumed := if (free <= rem) { free } else { rem }. + self.outbuf replaceFrom: self.outlen count: consumed with: byte_array startingAt: pos. + self.outlen := self.outlen + consumed. + }. + + pos := pos + consumed. + rem := rem - consumed. + }. + + ^count - rem. + } + + method flush + { + | v pos | + + pos := 0. + while (pos < self.outlen) + { + v := self.bsobj writeBytesFrom: self.outbuf offset: pos length: (self.outlen - pos). + if (v <= 0) { break }. ## TODO: error handling. also handle exceptions + pos := pos + v. + }. + + self.outlen := 0. + } +} + +class ByteStream(ByteStreamAdapter) +{ + method close + { + if (self.bsobj notNil) + { + self.bsobj close. + self.bsobj := nil. + }. + } +} + +class TextStream(ByteStream) +{ } + diff --git a/moo/lib/comp.c b/moo/lib/comp.c index dd0e83b..c77c2a8 100644 --- a/moo/lib/comp.c +++ b/moo/lib/comp.c @@ -5034,8 +5034,8 @@ static int compile_expression_primary (moo_t* moo, const moo_oocs_t* ident, cons switch (TOKEN_TYPE(moo)) { case MOO_IOTOK_IDENT_DOTTED: - ident_dotted = 1; case MOO_IOTOK_IDENT: + ident_dotted = (TOKEN_TYPE(moo) == MOO_IOTOK_IDENT_DOTTED); ident = TOKEN_NAME(moo); ident_loc = TOKEN_LOC(moo); read_next_token = 1; diff --git a/moo/mod/sck.c b/moo/mod/sck.c index 1eb79c1..28a3fc7 100644 --- a/moo/mod/sck.c +++ b/moo/mod/sck.c @@ -592,11 +592,11 @@ static moo_pfinfo_t pfinfos[] = { I, { 'c','o','n','n','e','c','t',':','\0' }, 0, { pf_connect_socket, 1, 1 } }, { I, { 'l','i','s','t','e','n',':','\0' }, 0, { pf_listen_socket, 1, 1 } }, { I, { 'o','p','e','n','\0' }, 0, { pf_open_socket, 1, 3 } }, - { I, { 'r','e','a','d','B','y','t','e','s',':','\0' }, 0, { pf_read_socket, 1, 1 } }, - { I, { 'r','e','a','d','B','y','t','e','s',':','o','f','f','s','e','t',':','l','e','n','g','t','h',':','\0' }, 0, { pf_read_socket, 3, 3 } }, + { I, { 'r','e','a','d','B','y','t','e','s','I','n','t','o',':','\0' }, 0, { pf_read_socket, 1, 1 } }, + { I, { 'r','e','a','d','B','y','t','e','s','I','n','t','o',':','o','f','f','s','e','t',':','l','e','n','g','t','h',':','\0' }, 0, { pf_read_socket, 3, 3 } }, { I, { 's','o','c','k','e','t','E','r','r','o','r','\0' }, 0, { pf_get_socket_error, 0, 0 } }, - { I, { 'w','r','i','t','e','B','y','t','e','s',':','\0' }, 0, { pf_write_socket, 1, 1 } }, - { I, { 'w','r','i','t','e','B','y','t','e','s',':','o','f','f','s','e','t',':','l','e','n','g','t','h',':','\0' }, 0, { pf_write_socket, 3, 3 } } + { I, { 'w','r','i','t','e','B','y','t','e','s','F','r','o','m',':','\0' }, 0, { pf_write_socket, 1, 1 } }, + { I, { 'w','r','i','t','e','B','y','t','e','s','F','r','o','m',':','o','f','f','s','e','t',':','l','e','n','g','t','h',':','\0' }, 0, { pf_write_socket, 3, 3 } } }; /* ------------------------------------------------------------------------ */