Skip to content

Commit ff6cb73

Browse files
committed
feat: impl http 1.1 basic feature
fixed a bug causing `if let..`'s condition eval twice during exe. update bin op parser so that bin op can eat new line
1 parent adef328 commit ff6cb73

File tree

13 files changed

+168
-55
lines changed

13 files changed

+168
-55
lines changed

planglib/std/task/http.pi

Lines changed: 70 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
use std::task::Task;
22
use std::task::tcp;
3+
use std::task::dns;
34
use std::string::StringBuilder;
45
use std::string::StringExt;
6+
use std::cols::arr;
57

68
pub struct HttpResponse {
79
status_code: i32;
810
headers: string;
9-
body: [u8];
11+
socket: tcp::TCPSocket;
12+
body_read: bool;
13+
cached_body: arr::Array<u8>; // 新增:缓存已读取的body内容
1014
}
1115

1216
pub struct HttpClient {
@@ -19,6 +23,7 @@ pub fn new_http_client() HttpClient {
1923
};
2024
}
2125

26+
use std::io;
2227
impl HttpClient {
2328
pub async fn get_async(url: string) Task<HttpResponse> {
2429
// 构建HTTP GET请求
@@ -34,51 +39,89 @@ impl HttpClient {
3439

3540
let request = sb.str();
3641
let bytes = request.bytes();
37-
let status = await self.socket.connect_async("127.0.0.1", 5500 as i32);
42+
let resolver = dns::new_dns_resolver();
43+
let ip = await resolver.resolve_async(url);
44+
let status = await self.socket.connect_async(ip, 80 as i32);
3845
// 发送请求
3946
await self.socket.write_async(bytes);
4047

41-
// 读取响应
42-
let response_buf = [u8*4096;];
43-
let read_len = await self.socket.read_async(response_buf);
44-
45-
// let response_str = string_from_bytes(arr_slice(response_buf, 0, read_len));
48+
// 使用1k缓冲区读取header
49+
let response_buf = [u8*1024;];
50+
let total_read = 0;
51+
let header_end = -1;
4652

47-
// 手动解析响应
48-
let header_end = 0;
49-
// 查找headers和body的分隔符 \r\n\r\n
50-
for let i = 0; i < read_len - 3; i = i + 1 {
51-
if response_buf[i] == '\r' as u8 && response_buf[i+1] == '\n' as u8 &&response_buf[i+2] == '\r' as u8 &&response_buf[i+3] == '\n' as u8 {
52-
header_end = i;
53+
while header_end == -1 {
54+
let read_len = await self.socket.read_async(response_buf);
55+
if read_len == 0 {
5356
break;
5457
}
58+
59+
// 查找header结束位置
60+
for let i = 0; i < read_len - 3; i = i + 1 {
61+
if response_buf[i] as char == '\r' &&
62+
response_buf[i+1] as char == '\n' &&
63+
response_buf[i+2] as char == '\r' &&
64+
response_buf[i+3] as char == '\n' {
65+
header_end = total_read + i;
66+
break;
67+
}
68+
}
69+
total_read = total_read + read_len;
5570
}
5671

5772
let headers = string_from_bytes(arr_slice(response_buf, 0, header_end));
58-
let body = arr_slice(response_buf, header_end + 4, read_len - (header_end + 4));
73+
74+
// 缓存已读取的body内容
75+
let body_start = header_end + 4;
76+
let cached_body = arr::from_slice<u8>(arr_slice(response_buf, body_start, total_read - body_start));
5977

6078
// 解析状态码
61-
let status_start = 9; // "HTTP/1.1 "的长度
62-
let status_end = status_start;
63-
for let i = status_start; i < header_end; i = i + 1 {
64-
if response_buf[i] == ' ' as u8 {
65-
status_end = i;
66-
break;
67-
}
68-
}
69-
let status_str = string_from_bytes(arr_slice(response_buf, status_start, status_end - status_start));
70-
// TODO: 将status_str转换为整数
79+
let status_str = string_from_bytes(arr_slice(response_buf, 9, 12));
7180

7281
return HttpResponse{
7382
status_code: 200 as i32,
7483
headers: headers,
75-
body: body,
84+
socket: self.socket,
85+
body_read: false,
86+
cached_body: cached_body,
7687
};
7788
}
7889
}
7990

91+
use std::math::*;
92+
use std::slice::SliceExt;
93+
8094
impl HttpResponse {
81-
pub fn get_body_string() string {
82-
return string_from_bytes(self.body);
95+
96+
pub async fn read_async(buf: [u8]) Task<Option<i64>> {
97+
if self.body_read {
98+
return None{} as Option<i64>;
99+
}
100+
// 先读取缓存的body内容
101+
if self.cached_body.length() > 0 {
102+
let copy_len = min(buf.len(), self.cached_body.length() as i64);
103+
arr_copy(self.cached_body.get_slice(), buf, copy_len);
104+
self.cached_body = arr::from_slice(arr_slice(self.cached_body.get_slice(), copy_len, self.cached_body.length() as i64 - copy_len));
105+
return copy_len as Option<i64>;
106+
}
107+
// 继续从socket读取
108+
let n = await self.socket.read_async(buf);
109+
if n == 0 {
110+
self.body_read = true;
111+
}
112+
return n as Option<i64>;
113+
}
114+
115+
pub async fn read_all_async() Task<[u8]> {
116+
let content = arr::new<u8>();
117+
let buf = [u8*4096;];
118+
while true {
119+
if let n = (await self.read_async(buf)) as i64 {
120+
content.append(arr::from_slice(arr_slice(buf, 0, n)));
121+
} else {
122+
break;
123+
}
124+
}
125+
return content.get_slice();
83126
}
84127
}

src/ast/builder/llvmbuilder.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2212,14 +2212,15 @@ impl<'a, 'ctx> IRBuilder<'a, 'ctx> for LLVMBuilder<'a, 'ctx> {
22122212
}
22132213
fn build_dbg_location(&self, pos: Pos) {
22142214
// assert_ne!(pos.line, 0, "debug location's line number should not be 0");
2215-
if self
2216-
.builder
2217-
.get_insert_block()
2218-
.unwrap()
2219-
.get_parent()
2220-
.unwrap()
2221-
.get_subprogram()
2222-
.is_none()
2215+
if self.builder.get_insert_block().is_none()
2216+
|| self
2217+
.builder
2218+
.get_insert_block()
2219+
.unwrap()
2220+
.get_parent()
2221+
.unwrap()
2222+
.get_subprogram()
2223+
.is_none()
22232224
{
22242225
return;
22252226
}

src/ast/fmt.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use super::{
1010
global::{GlobalConstNode, GlobalNode},
1111
implement::ImplNode,
1212
interface::{MultiTraitNode, TraitBoundNode, TraitDefNode},
13+
intermediate_node::IntermediateNode,
1314
macro_nodes::{MacroCallNode, MacroLoopStatementNode, MacroNode, MacroRuleNode},
1415
operator::{BinOpNode, TakeOpNode, UnaryOpNode},
1516
pkg::{ExternIdNode, UseNode},
@@ -941,4 +942,6 @@ impl FmtBuilder {
941942
super::node::control::MatchArmCondition::TypedDeconstruct(_, _) => todo!(),
942943
}
943944
}
945+
946+
pub fn parse_intermediate_node(&mut self, _node: &IntermediateNode) {}
944947
}

src/ast/node/control.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,11 @@ impl Node for IfNode {
7373
.clone(),
7474
);
7575
}
76+
77+
// we need to evaluate the expr first, to avoid it run twice
78+
let inter = IntermediateNode::new(a.expr.clone().emit(ctx, builder));
7679
let mut transformed_is = NodeEnum::IsNode(IsNode {
77-
expr: a.expr.clone(),
80+
expr: Box::new(NodeEnum::InterNode(inter.clone())),
7881
target_type: a.target_type.clone(),
7982
range: a.range(),
8083
});
@@ -88,7 +91,7 @@ impl Node for IfNode {
8891
);
8992
ctx.position_at_end(then_block, builder);
9093
let transformed_as = NodeEnum::AsNode(AsNode {
91-
expr: a.expr.clone(),
94+
expr: Box::new(NodeEnum::InterNode(inter)),
9295
target_type: a.target_type.clone(),
9396
range: a.range(),
9497
tail: Some((TokenType::NOT, Default::default())),
@@ -105,8 +108,10 @@ impl Node for IfNode {
105108
.clone(),
106109
);
107110
}
111+
// we need to evaluate the expr first, to avoid it run twice
112+
let inter = IntermediateNode::new(a.expr.clone().emit(ctx, builder));
108113
let mut transformed_is = NodeEnum::ImplCastNode(ImplCastNode {
109-
expr: a.expr.clone(),
114+
expr: Box::new(NodeEnum::InterNode(inter.clone())),
110115
target_type: a.target_type.clone(),
111116
range: a.range(),
112117
tail: Some((TokenType::QUESTION, Default::default())),
@@ -128,7 +133,7 @@ impl Node for IfNode {
128133
}
129134
ctx.position_at_end(then_block, builder);
130135
let transformed_as = NodeEnum::ImplCastNode(ImplCastNode {
131-
expr: a.expr.clone(),
136+
expr: Box::new(NodeEnum::InterNode(inter)),
132137
target_type: a.target_type.clone(),
133138
range: a.range(),
134139
tail: Some((TokenType::NOT, Default::default())),

src/ast/node/intermediate_node.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
use crate::ast::{ctx::Ctx, range::Range};
2+
use internal_macro::node;
3+
4+
use crate::ast::builder::BuilderEnum;
5+
6+
use super::node_result::NodeResult;
7+
use super::{Node, PrintTrait};
8+
9+
#[node]
10+
pub struct IntermediateNode {
11+
value: NodeResult,
12+
}
13+
14+
// this node will never be shared between threads
15+
unsafe impl Send for IntermediateNode {}
16+
unsafe impl Sync for IntermediateNode {}
17+
18+
impl IntermediateNode {
19+
pub fn new(value: NodeResult) -> Self {
20+
Self {
21+
value,
22+
range: Range::default(),
23+
}
24+
}
25+
}
26+
27+
impl PrintTrait for IntermediateNode {
28+
fn print(&self, _tabs: usize, _end: bool, _line: Vec<bool>) {
29+
unreachable!()
30+
}
31+
}
32+
33+
impl Node for IntermediateNode {
34+
fn emit<'a, 'b>(
35+
&mut self,
36+
_ctx: &'b mut Ctx<'a>,
37+
_builder: &'b BuilderEnum<'a, '_>,
38+
) -> NodeResult {
39+
self.value.clone()
40+
}
41+
}

src/ast/node/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use crate::ast::builder::IRBuilder;
99
use cast::ImplCastNode;
1010
use enum_dispatch::enum_dispatch;
1111

12+
use intermediate_node::IntermediateNode;
1213
use lsp_types::SemanticTokenType;
1314

1415
use self::cast::AsNode;
@@ -54,6 +55,7 @@ pub mod function;
5455
pub mod global;
5556
pub mod implement;
5657
pub mod interface;
58+
pub mod intermediate_node;
5759
pub mod macro_nodes;
5860
pub mod node_result;
5961
pub mod operator;
@@ -148,6 +150,7 @@ pub enum NodeEnum {
148150
ClosureNode(ClosureNode),
149151
GlobalConstNode(GlobalConstNode),
150152
MatchNode(MatchNode),
153+
InterNode(IntermediateNode),
151154
}
152155
// ANCHOR: range
153156
#[enum_dispatch]

src/ast/node/node_result.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,14 @@ impl TerminatorEnum {
2222
}
2323
}
2424

25-
#[derive(Default, Clone)]
25+
#[derive(Default, Clone, PartialEq, Eq, Debug)]
2626
pub struct NodeOutput {
2727
value: Option<NodeValue>,
2828
term: TerminatorEnum,
2929
pub compile_time_result: CompileTimeResult,
3030
}
3131

32-
#[derive(Debug, Clone, Default, Copy)]
32+
#[derive(Debug, Clone, Default, Copy, PartialEq, Eq)]
3333
pub enum CompileTimeResult {
3434
#[default]
3535
None,
@@ -140,7 +140,7 @@ impl NodeOutput {
140140
}
141141

142142
/// NodeValue is the output of the builder
143-
#[derive(Debug, Clone)]
143+
#[derive(Debug, Clone, PartialEq, Eq)]
144144
pub struct NodeValue {
145145
/// the index which maps the real value stored inside the LLVMBuilder
146146
value: ValueHandle,

src/nomparser/array.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,20 @@ use super::*;
2929
pub fn array_init(input: Span) -> IResult<Span, Box<NodeEnum>> {
3030
map_res(
3131
tuple((
32-
tag_token_symbol(TokenType::LBRACKET),
32+
tag_token_symbol_ex(TokenType::LBRACKET),
3333
opt(pair(
3434
type_name,
3535
delimited(
36-
tag_token_symbol(TokenType::MUL),
36+
tag_token_symbol_ex(TokenType::MUL),
3737
general_exp,
38-
tag_token_symbol(TokenType::SEMI),
38+
tag_token_symbol_ex(TokenType::SEMI),
3939
),
4040
)),
4141
separated_list0(
42-
tag_token_symbol(TokenType::COMMA),
42+
tag_token_symbol_ex(TokenType::COMMA),
4343
del_newline_or_space!(general_exp),
4444
),
45-
tag_token_symbol(TokenType::RBRACKET),
45+
tag_token_symbol_ex(TokenType::RBRACKET),
4646
)),
4747
// lb and rb are used to mark the boundaries of an arry.
4848
|((_, lb), tp, exps, (_, rb))| {
@@ -57,9 +57,9 @@ pub fn array_init(input: Span) -> IResult<Span, Box<NodeEnum>> {
5757
pub fn array_element_op(input: Span) -> IResult<Span, (ComplexOp, Vec<Box<NodeEnum>>)> {
5858
delspace(map_res(
5959
tuple((
60-
tag_token_symbol(TokenType::LBRACKET),
60+
tag_token_symbol_ex(TokenType::LBRACKET),
6161
opt(general_exp),
62-
tag_token_symbol(TokenType::RBRACKET),
62+
tag_token_symbol_ex(TokenType::RBRACKET),
6363
many0(comment),
6464
)),
6565
|(_, idx, (_, rr), com)| {

src/nomparser/control.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,14 @@ pub use _match::*;
2323
a = 2;
2424
}"
2525
)]
26+
#[test_parser(
27+
"if a > 1 ||
28+
b > 2 {
29+
a = 1;
30+
} else {
31+
a = 2;
32+
}"
33+
)]
2634
#[test_parser(
2735
"if true {
2836
a = 1;

src/nomparser/expression.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@ pub fn general_exp(input: Span) -> IResult<Span, Box<NodeEnum>> {
2929
#[test_parser("a&&b")]
3030
#[test_parser("a||b")]
3131
#[test_parser("a && b")]
32+
#[test_parser(
33+
"a &&
34+
b"
35+
)]
36+
#[test_parser(
37+
"a ||
38+
b"
39+
)]
3240
#[test_parser("a || b")]
3341
#[test_parser("a&&b||c")]
3442
#[test_parser("a||b&&c")]

src/nomparser/macros.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ macro_rules! parse_bin_ops {
2929
many0(tuple((
3030
alt((
3131
$(
32-
tag_token_symbol(TokenType::$op),
32+
tag_token_symbol_ex(TokenType::$op),
3333
)*
3434
)),
3535
$exp,

0 commit comments

Comments
 (0)