Skip to content

Commit d58acb0

Browse files
authored
Merge pull request #1 from ShiSeAB/add-exercise-solution
2 parents 7e85cb9 + 1c6554e commit d58acb0

5 files changed

Lines changed: 983 additions & 9 deletions

File tree

exercises/index.html

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -132,29 +132,29 @@ <h2>语法分析 (Parsing)</h2>
132132
<span class="badge coming">即将推出</span>
133133
</div>
134134

135-
<div class="card coming-soon">
135+
<a href="sem.html" class="card available">
136136
<h2>语义分析 (Semantic Analysis)</h2>
137137
<p>符号表、类型检查、作用域规则</p>
138-
<span class="badge coming">即将推出</span>
139-
</div>
138+
<span class="badge available">可用</span>
139+
</a>
140140

141-
<div class="card coming-soon">
141+
<a href="ir.html" class="card available">
142142
<h2>中间表示 (IR)</h2>
143143
<p>IR树、翻译、逃逸分析</p>
144-
<span class="badge coming">即将推出</span>
145-
</div>
144+
<span class="badge available">可用</span>
145+
</a>
146146

147147
<div class="card coming-soon">
148148
<h2>规范化 (Canonicalization)</h2>
149149
<p>基本块、线性化、轨迹调度</p>
150150
<span class="badge coming">即将推出</span>
151151
</div>
152152

153-
<div class="card coming-soon">
153+
<a href="inst.html" class="card available">
154154
<h2>指令选择 (Instruction Selection)</h2>
155155
<p>树模式匹配、汇编代码生成</p>
156-
<span class="badge coming">即将推出</span>
157-
</div>
156+
<span class="badge available">可用</span>
157+
</a>
158158

159159
<div class="card coming-soon">
160160
<h2>活跃性分析 (Liveness Analysis)</h2>

exercises/inst.html

Lines changed: 315 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,315 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8">
5+
<title>Compiler Design Quiz</title>
6+
<meta name="viewport" content="width=device-width,initial-scale=1">
7+
<style>
8+
:root{
9+
--ok:#4caf50; --bad:#f44336; --border:#bbb;
10+
--bg:#fafafa; --fg:#222; --accent:#1565c0;
11+
}
12+
body{font-family:system-ui,Segoe UI,Roboto,sans-serif;margin:0;background:var(--bg);color:var(--fg);}
13+
header{padding:1rem;background:var(--accent);color:#fff;text-align:center;}
14+
main{padding:1rem;max-width:820px;margin:auto;}
15+
h2{margin-top:2rem;color:var(--accent); border-bottom: 2px solid #eee; padding-bottom: 0.5rem;}
16+
.q{padding:1rem;border:1px solid var(--border);border-radius:6px;margin-bottom:.8rem;background:#fff; transition: background 0.3s;}
17+
.q.correct{border-color:var(--ok);background:#f1f8f4;}
18+
.q.wrong {border-color:var(--bad);background:#fef5f5;}
19+
label.option-label{display:block;padding:.4rem 0;cursor:pointer; transition: color 0.2s;}
20+
button{padding:.6rem 1rem;margin:1.5rem 0;font-size:1rem;border:none;border-radius:4px;background:var(--accent);color:#fff;cursor:pointer; transition: background 0.3s;}
21+
.check-btn { padding: 0.4rem 0.8rem; margin: 0.5rem 0 0 0; font-size: 0.9rem; }
22+
button:hover:not(:disabled){background:#0d47a1;}
23+
button:disabled{opacity:.6;cursor:not-allowed;}
24+
#result{font-weight:bold;font-size:1.1rem;margin-top:1rem;padding:1rem;border-radius:4px; display:none;}
25+
#result.show{display:block; background:#e3f2fd;border:1px solid var(--accent);}
26+
footer{padding:1rem;text-align:center;font-size:.85rem;color:#555;}
27+
28+
/* 代码块与解析的样式 */
29+
code { background: #eee; padding: 2px 5px; border-radius: 4px; color: #d63384; font-family: monospace; }
30+
.explanation {
31+
display: none;
32+
margin-top: 0.2rem;
33+
margin-bottom: 0.8rem;
34+
padding: 0.6rem;
35+
background-color: #f9f9f9;
36+
border-left: 3px solid var(--accent);
37+
font-size: 0.9rem;
38+
color: #444;
39+
white-space: pre-wrap; /* 保留文本中的换行符 */
40+
}
41+
.explanation.show {
42+
display: block;
43+
animation: fadeIn 0.4s ease;
44+
}
45+
@keyframes fadeIn { from { opacity: 0; transform: translateY(-5px); } to { opacity: 1; transform: translateY(0); } }
46+
@media(max-width:500px){body{font-size:15px;}}
47+
</style>
48+
49+
<!-- 引入 MathJax 以支持类似于 $\sigma_1$ 的 LaTeX 公式渲染 -->
50+
<script>
51+
MathJax = {
52+
tex: { inlineMath: [['$', '$'], ['\\(', '\\)']] }
53+
};
54+
</script>
55+
<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
56+
</head>
57+
<body>
58+
<header><h1>Compiler Design – Self-Check Quiz</h1></header>
59+
<main>
60+
<section id="tf"><h2>True / False</h2></section>
61+
<section id="mcq"><h2>Multiple Choice</h2></section>
62+
<div id="result"></div>
63+
</main>
64+
<footer>
65+
<p>Based on Compiler Design chapters. © 2026</p>
66+
<p style="margin-top: 1rem; font-size: 0.85rem;">
67+
📖 源码与贡献题目请访问:<a href="https://github.com/rainoftime/tiger/tree/main/exercises" target="_blank" style="color: var(--accent); text-decoration: none;">GitHub Exercises</a>
68+
</p>
69+
</footer>
70+
71+
<script>
72+
const tfWrap = document.getElementById('tf');
73+
const mcqWrap = document.getElementById('mcq');
74+
const resultBox = document.getElementById('result');
75+
76+
// 格式化文本:将反引号包裹的文本转换为 HTML 的 <code> 标签
77+
function formatText(text) {
78+
if(!text) return "";
79+
return text.replace(/`([^`]+)`/g, '<code>$1</code>');
80+
}
81+
82+
// build multiple choice / TF element
83+
function buildMCQ(q, globalIdx, labelPrefix = "Q"){
84+
const div = document.createElement('div');
85+
div.className = 'q';
86+
div.dataset.correct = q.answer; // store index
87+
let optionsHTML = '';
88+
89+
q.options.forEach((opt, idx) => {
90+
// 只有当有解析时才渲染解析 div
91+
const expHTML = opt.explanation ? `<div class="explanation">${formatText(opt.explanation)}</div>` : '';
92+
optionsHTML += `
93+
<label class="option-label" id="lbl-${globalIdx}-${idx}">
94+
<input type="radio" name="q${globalIdx}" value="${idx}">
95+
<span class="opt-text">${formatText(opt.text)}</span>
96+
</label>
97+
${expHTML}
98+
`;
99+
});
100+
101+
div.innerHTML=`<strong>${labelPrefix}.</strong> ${formatText(q.question)}<br><div style="margin-top:0.8rem;">${optionsHTML}</div>
102+
<button class="check-btn" id="btn-${globalIdx}">Check Answer / 查看解析</button>`;
103+
return div;
104+
}
105+
106+
// 每道题单独的判定逻辑
107+
function gradeQuestion(div, qIndex, btn) {
108+
const correctIdx = parseInt(div.dataset.correct);
109+
const sel = div.querySelector('input[type=radio]:checked');
110+
111+
// 如果没有选择,设定 selectedIdx 为 -1
112+
const selectedIdx = sel ? parseInt(sel.value) : -1;
113+
114+
// 判断对错(未作答视为错误)
115+
if(selectedIdx === correctIdx){
116+
div.classList.add('correct');
117+
}else{
118+
div.classList.add('wrong');
119+
}
120+
121+
// 显示解析
122+
div.querySelectorAll('.explanation').forEach(exp => exp.classList.add('show'));
123+
124+
// 高亮选项颜色(正确答案标绿加粗,选错的标红)
125+
div.querySelectorAll('.option-label').forEach((lbl, idx) => {
126+
const radio = lbl.querySelector('input');
127+
radio.disabled = true; // 提交后禁用选项
128+
129+
// 增加 padding 以适应背景色高亮
130+
lbl.style.padding = '0.4rem 0.5rem';
131+
lbl.style.borderRadius = '4px';
132+
133+
if (idx === correctIdx) {
134+
lbl.style.color = '#2e7d32';
135+
lbl.style.fontWeight = 'bold';
136+
lbl.style.backgroundColor = '#e8f5e9'; // 浅绿色背景
137+
lbl.querySelector('.opt-text').innerHTML += ' ✅';
138+
} else if (idx === selectedIdx && selectedIdx !== correctIdx) {
139+
lbl.style.color = '#c62828';
140+
lbl.style.fontWeight = 'bold';
141+
lbl.style.backgroundColor = '#ffebee'; // 浅红色背景
142+
lbl.querySelector('.opt-text').innerHTML += ' ❌';
143+
}
144+
});
145+
146+
btn.disabled = true;
147+
btn.textContent = 'Answered (已显示解析)';
148+
149+
checkAllFinished();
150+
}
151+
152+
// 检查是否所有题目均已作答,完成后显示总分
153+
function checkAllFinished() {
154+
const total = quizData.trueFalse.length + quizData.multipleChoice.length;
155+
const answered = document.querySelectorAll('.q.correct, .q.wrong').length;
156+
if (answered === total) {
157+
const correct = document.querySelectorAll('.q.correct').length;
158+
resultBox.innerHTML = `All Answered! Final Score (您的总成绩): ${correct} / ${total} (${Math.round(correct/total*100)}%)`;
159+
resultBox.classList.add('show');
160+
}
161+
}
162+
163+
// 数据结构化 (新增了 True/False 和 指令选择 的多选题)
164+
const quizData = {
165+
trueFalse: [
166+
{
167+
question: "Every optimum tiling is also an optimal tiling.",
168+
options: [
169+
{ text: "True", explanation: "正确答案\nAn optimum tiling is the global best; if it weren't optimal, you could combine two tiles to get a better result, contradicting its status as the 'optimum'." },
170+
{ text: "False", explanation: "By definition, the global minimum (optimum) must also satisfy the local criteria for an optimal tiling." }
171+
],
172+
answer: 0
173+
},
174+
{
175+
question: "The 'Maximal Munch' algorithm is guaranteed to find an 'optimum' tiling.",
176+
options: [
177+
{ text: "True", explanation: "Maximal Munch only guarantees an 'optimal' tiling (locally efficient), not necessarily the 'optimum' (globally least cost)." },
178+
{ text: "False", explanation: "正确答案\nMaximal Munch is a greedy algorithm; while it finds an optimal tiling, it may miss a lower-cost global solution found by dynamic programming." }
179+
],
180+
answer: 1
181+
},
182+
{
183+
question: "Instruction selection algorithms like Maximal Munch have a time complexity that is linear in terms of the number of nodes in the IR tree.",
184+
options: [
185+
{ text: "True", explanation: "正确答案\nThe algorithms perform a fixed amount of work per node (or per munch), resulting in O(N) efficiency." },
186+
{ text: "False", explanation: "Despite the complexity of patterns, the matching process is highly efficient and scales linearly with the size of the input tree." }
187+
],
188+
answer: 0
189+
},
190+
{
191+
question: "Instructions with side effects, such as autoincrement, are easily and naturally expressed using tree patterns.",
192+
options: [
193+
{ text: "True", explanation: "Tree patterns are best suited for instructions that produce a single result; side effects usually require DAG-based patterns or ad hoc handling." },
194+
{ text: "False", explanation: "正确答案\nThe tree structure makes it difficult to represent an instruction that produces multiple results or updates multiple registers simultaneously." }
195+
],
196+
answer: 1
197+
},
198+
{
199+
question: "Dynamic programming for instruction selection works in a top-down fashion.",
200+
options: [
201+
{ text: "True", explanation: "Maximal Munch is top-down; dynamic programming is bottom-up because it needs the costs of subtrees to compute the cost of the parent." },
202+
{ text: "False", explanation: "正确答案\nDynamic programming is a bottom-up technique that calculates costs starting from the leaves and moving toward the root." }
203+
],
204+
answer: 1
205+
},
206+
{
207+
question: "In the Schizo-Jouette architecture example, register r0 always contains the value zero.",
208+
options: [
209+
{ text: "True", explanation: "正确答案\nThis is a common feature of many architectures (like MIPS) and is explicitly stated as a property of the Jouette machine." },
210+
{ text: "False", explanation: "The source explicitly mentions that r0 is hardwired to zero in this architectural model." }
211+
],
212+
answer: 0
213+
}
214+
],
215+
multipleChoice: [
216+
{
217+
question: "In a tree-based intermediate representation (IR), what is the primary characteristic of each tree node?",
218+
options: [
219+
{ text: "A. It can encapsulate multiple side effects like autoincrement and assignment.", explanation: "Complex side effects are typically features of machine instructions, not the simplified IR tree nodes." },
220+
{ text: "B. It is always 32 bits long to match the target architecture's word size.", explanation: "IR nodes are abstract data structures in the compiler, not physical machine words with fixed bit lengths." },
221+
{ text: "C. It represents a complete machine instruction including all addressing modes.", explanation: "Machine instructions often combine several primitive operations, whereas the IR nodes represent these primitives individually." },
222+
{ text: "D. It expresses only one primitive operation, such as a memory fetch or addition.", explanation: "正确答案\nThe IR is designed to be granular, representing single operations like memory access or arithmetic, which are later combined into machine instructions." }
223+
],
224+
answer: 3
225+
},
226+
{
227+
question: "Which of the following best describes an 'optimum' tiling in instruction selection?",
228+
options: [
229+
{ text: "A. A tiling that uses the maximum number of nodes in each individual tile.", explanation: "Using the largest possible tiles (Maximal Munch) guarantees an optimal tiling, but not necessarily the optimum (lowest cost) one." },
230+
{ text: "B. A tiling whose tiles sum to the lowest possible total cost for the entire tree.", explanation: "正确答案\nAn optimum tiling represents the global minimum cost based on the provided instruction cost model." },
231+
{ text: "C. A tiling where no two adjacent tiles can be combined into a lower-cost single tile.", explanation: "This describes an 'optimal' tiling, which is a local property rather than a global one." },
232+
{ text: "D. A tiling that produces the longest sequence of instructions to ensure safety.", explanation: "The goal of tiling is efficiency, so the shortest or least-cost sequence is generally preferred." }
233+
],
234+
answer: 1
235+
},
236+
{
237+
question: "How does the 'Maximal Munch' algorithm select tiles during instruction selection?",
238+
options: [
239+
{ text: "A. It randomly selects between matching tiles to avoid compiler bias.", explanation: "While it can be arbitrary if tile sizes are equal, the selection is based on tile size (number of nodes)." },
240+
{ text: "B. It examines every possible combination of tiles to find the absolute lowest cost.", explanation: "This describes dynamic programming; Maximal Munch uses a greedy approach." },
241+
{ text: "C. It starts at the root and finds the largest tile that fits, then repeats for the subtrees.", explanation: "正确答案\nMaximal Munch is a greedy top-down algorithm that prioritizes the tile covering the most nodes at the current root." },
242+
{ text: "D. It starts at the leaves and works upward to find the best match at the root.", explanation: "Maximal Munch is a top-down algorithm that begins at the root of the tree." }
243+
],
244+
answer: 2
245+
},
246+
{
247+
question: "On a machine without a physical frame pointer, how is a reference to the virtual frame pointer (FP+k) typically resolved?",
248+
options: [
249+
{ text: "A. It is replaced with SP+k+fs, where fs is the frame size.", explanation: "正确答案\nThe virtual frame pointer's position relative to the stack pointer depends on the total size of the current stack frame." },
250+
{ text: "B. It is ignored, and the compiler uses absolute memory addresses instead.", explanation: "Compilers must use relative addressing (via SP) because the absolute address of a stack frame varies at runtime." },
251+
{ text: "C. It is replaced by SP−k to account for stack growth directions.", explanation: "The offset depends on the frame size fs and how the virtual FP was defined relative to the SP at the start of the frame." },
252+
{ text: "D. It is resolved by allocating a dedicated register at runtime to act as a frame pointer.", explanation: "The question specifies a machine without a physical frame pointer; SP is used to simulate it mathematically." }
253+
],
254+
answer: 0
255+
},
256+
{
257+
question: "Which of the following is a significant challenge when trying to use tree patterns for instructions with 'side effects,' such as autoincrementing a register after a memory fetch?",
258+
options: [
259+
{ text: "A. The Jouette architecture forbids instructions with side effects.", explanation: "While Jouette is simple, the question is about the general limitation of the tree pattern-matching technique across different architectures." },
260+
{ text: "B. Tree patterns can only represent a single result or effect per tile.", explanation: "正确答案\nStandard tree patterns represent a single value or effect; instructions that produce two results (like a value and an incremented pointer) are difficult to capture in one tree." },
261+
{ text: "C. Side effects require the use of more than 32 registers.", explanation: "Register count is independent of whether an instruction has side effects or can be modeled by a tree pattern." },
262+
{ text: "D. Side effects make the matching algorithm run in exponential time.", explanation: "The algorithm remains linear; the difficulty lies in the structural representation of the instruction, not the computational complexity of the match." }
263+
],
264+
answer: 1
265+
},
266+
{
267+
question: "When implementing instruction selection for a CISC machine with two-address instructions (e.g., r1←r1+r2), how is a three-address IR operation like t1←t2+t3 typically handled?",
268+
options: [
269+
{ text: "A. By generating a MOVE instruction to copy t2 to t1, followed by an ADD instruction t1←t1+t3.", explanation: "正确答案\nTo simulate a three-address operation on two-address hardware, the source is moved to the destination first, and then the operation is performed in-place." },
270+
{ text: "B. By ignoring the instruction and hoping the register allocator finds a single instruction that matches.", explanation: "The instruction selector must emit valid assembly; it cannot leave IR nodes unimplemented for the allocator." },
271+
{ text: "C. By using a special MEM node to store the intermediate result of the addition.", explanation: "Storing to memory is inefficient; the standard approach uses temporary registers and extra moves which the allocator can later optimize." },
272+
{ text: "D. By forcing the register allocator to assign t1,t2, and t3 to the same physical register.", explanation: "This is often impossible if the values need to remain distinct; moves are the standard solution to preserve correctness." }
273+
],
274+
answer: 0
275+
},
276+
{
277+
question: "In the Jouette architecture examples, which instruction would typically be generated for the IR pattern BINOP(PLUS,e1,CONST(i))?",
278+
options:[
279+
{ text: "A. STORE", explanation: "A STORE instruction is used to move data from a register to memory, which corresponds to a MOVE(MEM(...),...) tree." },
280+
{ text: "B. MOVEM", explanation: "The MOVEM instruction in Jouette is specifically for memory-to-memory moves, which involves two MEM nodes." },
281+
{ text: "C. LOAD", explanation: "The LOAD instruction is used for memory fetches (MEM nodes), not for simple arithmetic additions with constants." },
282+
{ text: "D. ADDI", explanation: "正确答案\nThe ADDI (Add Immediate) instruction is designed to add a register value to a constant value, matching the PLUS operation with a CONST leaf." }
283+
],
284+
answer: 3
285+
},
286+
]
287+
};
288+
289+
// 动态构建界面
290+
let globalCounter = 0;
291+
292+
// 1. 渲染判断题
293+
quizData.trueFalse.forEach((q, i) => {
294+
const qDiv = buildMCQ(q, globalCounter, `T/F ${i+1}`);
295+
tfWrap.appendChild(qDiv);
296+
297+
const btn = qDiv.querySelector(`#btn-${globalCounter}`);
298+
const currentCounter = globalCounter;
299+
btn.addEventListener('click', () => gradeQuestion(qDiv, currentCounter, btn));
300+
globalCounter++;
301+
});
302+
303+
// 2. 渲染单选题
304+
quizData.multipleChoice.forEach((q, i) => {
305+
const qDiv = buildMCQ(q, globalCounter, `Q${i+1}`);
306+
mcqWrap.appendChild(qDiv);
307+
308+
const btn = qDiv.querySelector(`#btn-${globalCounter}`);
309+
const currentCounter = globalCounter;
310+
btn.addEventListener('click', () => gradeQuestion(qDiv, currentCounter, btn));
311+
globalCounter++;
312+
});
313+
</script>
314+
</body>
315+
</html>

0 commit comments

Comments
 (0)